일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 플러터 설치 2022
- 클래스
- jvm 작동 원리
- 안드로이드 라이선스
- android retrofit login
- 스택 큐 차이
- ANR이란
- 자바 다형성
- rxjava cold observable
- Rxjava Observable
- 서비스 쓰레드 차이
- 스택 자바 코드
- 큐 자바 코드
- 2022 플러터 안드로이드 스튜디오
- 안드로이드 라이선스 종류
- 안드로이드 레트로핏 crud
- 안드로이드 유닛 테스트
- ar vr 차이
- rxjava hot observable
- 2022 플러터 설치
- android ar 개발
- rxjava disposable
- 안드로이드 유닛 테스트 예시
- 멤버변수
- 안드로이드 레트로핏 사용법
- 안드로이드 유닛테스트란
- 객체
- jvm이란
- 서비스 vs 쓰레드
- 안드로이드 os 구조
- Today
- Total
나만을 위한 블로그
[Android] TextWatcher를 공통 클래스로 만드는 방법 본문
앱을 만들면서 editText를 다룰 때 제법 많이 사용하는 것이 TextWatcher라는 인터페이스다. 이것에 대한 설명은 아래 포스팅을 참고하거나 다른 블로그를 먼저 보고 오는 걸 추천한다.
https://onlyfor-me-blog.tistory.com/435
TextWatcher는 결국 인터페이스기 때문에 구현할 경우 3개 함수를 모두 재정의해야 한다. 이 함수들을 액티비티 안에 구현하는 경우 코틀린을 사용하더라도 많은 공간을 차지하게 된다. 얼마나 차지하는지를 먼저 확인하기 위해 먼저 화면부터 대충 준비한다.
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginHorizontal="20dp"
tools:context=".textwatcher.TextWatcherTestActivity">
<EditText
android:id="@+id/etFirst"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="100dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<EditText
android:id="@+id/etSecond"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="60dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/etFirst"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import androidx.databinding.DataBindingUtil
import com.example.kotlinprac.R
import com.example.kotlinprac.databinding.ActivityTextWatcherTestBinding
class TextWatcherTestActivity : AppCompatActivity() {
private val TAG = this.javaClass.simpleName
private lateinit var binding: ActivityTextWatcherTestBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_text_watcher_test)
binding.run {
lifecycleOwner = this@TextWatcherTestActivity
etFirst.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
TODO("Not yet implemented")
}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
TODO("Not yet implemented")
}
override fun afterTextChanged(p0: Editable?) {
TODO("Not yet implemented")
}
})
}
}
}
위의 코틀린 소스코드 기준으로 22~34번 줄까지 총 12줄을 TextWatcher 기본 구현만으로 잡아먹는다. 심지어 2개의 editText 중 하나에만 적용했는데도 이렇게 길다.
이 소스코드들이 editText가 있는 액티비티마다 존재한다면? 액티비티 / 프래그먼트 별 하는 작업은 다를 수 있지만 결국 함수 3개를 계속 반복구현하는 게 된다. 너무 귀찮다.
이 때 사용할 수 있는 방법이 TextWatcher를 구현하는 클래스를 만들고 주 생성자로 재정의 함수 3개에 각각 넣어줄 람다 함수를 선언하는 것이다. 이 방법은 아래 사이트에서 참고했다. 결론만 작성하고 앞단계는 건너뛰었으니 흥미있는 사람들은 한번 읽어보는 것도 좋겠다.
https://abangkis.medium.com/creating-dynamic-android-textwatcher-using-kotlin-fb5a4bc24996
아래 코드를 먼저 보자.
import android.text.Editable
import android.text.TextWatcher
class CommonTextWatcher(
private val afterChanged: ((Editable?) -> Unit) = {},
private val beforeChanged: ((CharSequence?, Int, Int, Int) -> Unit) = { _, _, _, _ -> },
private val onChanged: ((CharSequence?, Int, Int, Int) -> Unit) = { _, _, _, _ -> }
): TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
beforeChanged(s, start, count, after)
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
onChanged(s, start, before, count)
}
override fun afterTextChanged(s: Editable?) {
afterChanged(s)
}
}
개인적으로 TextWatcher를 많이 써보진 않았지만 사용하더라도 저 3개 함수를 모두 재정의해야겠다 싶은 경우는 거의 없을 것이라고 생각된다. 만약 있다면 기획을 바꿔야 한다
그래서 원하는 함수만 사용할 수 있게 하기 위해 nullable한 람다 함수를 매개변수로 받도록 했고, 매개변수 별로 기본값을 설정해놓은 걸 볼 수 있다.
이제 남은 건 위에서 만든 CommonTextWatcher를 액티비티에서 사용하는 것 뿐이다.
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import androidx.databinding.DataBindingUtil
import com.example.kotlinprac.R
import com.example.kotlinprac.databinding.ActivityTextWatcherTestBinding
class TextWatcherTestActivity : AppCompatActivity() {
private val TAG = this.javaClass.simpleName
private lateinit var binding: ActivityTextWatcherTestBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_text_watcher_test)
binding.run {
lifecycleOwner = this@TextWatcherTestActivity
etFirst.addTextChangedListener(CommonTextWatcher(
onChanged = { source, _, _, _ ->
Log.e(TAG, "etFirst - onChanged source : $source")
}
))
etSecond.addTextChangedListener(CommonTextWatcher(
afterChanged = { source ->
Log.e(TAG, "etSecond - afterChanged source : $source")
}
))
}
}
}
아주 깔끔하게 변했다. 2개의 editText에 모두 TextWatcher를 적용했음에도 위 소스코드 기준 21~31번 줄까지 총 10줄을 차지한다. 하나의 editText가 12줄을 잡아먹던 이전 코드에 비하면 매우 간결해졌다.
각각의 editText에 입력되는 값을 로그로 출력해보면 아래와 같이 잘 찍혀나온다.
그런데 위의 소스코드처럼 로그만 찍는 경우는 아래처럼 더 줄일 수도 있다.
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import androidx.databinding.DataBindingUtil
import com.example.kotlinprac.R
import com.example.kotlinprac.databinding.ActivityTextWatcherTestBinding
class TextWatcherTestActivity : AppCompatActivity() {
private val TAG = this.javaClass.simpleName
private lateinit var binding: ActivityTextWatcherTestBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_text_watcher_test)
binding.run {
lifecycleOwner = this@TextWatcherTestActivity
val commonTextWatcher = CommonTextWatcher(
afterChanged = { source ->
Log.e(TAG, "source : $source")
}
)
etFirst.addTextChangedListener(commonTextWatcher)
etSecond.addTextChangedListener(commonTextWatcher)
}
}
}
위 소스코드 기준 2개의 editText에 TextWatcher를 붙이는 것에 21~28번 줄까지 총 7줄만 사용하는 걸 볼 수 있다. 예시를 들기 위해 로그를 사용했지만 실제로는 저것보다 더 복잡한 함수나 코드들이 추가될 텐데, 그렇더라도 위의 방식을 응용한다면 소스코드가 훨씬 간결해질 것이다.
'Android' 카테고리의 다른 글
[Android] 이미지 캐시 (0) | 2022.10.03 |
---|---|
[Android] BindingAdapter란? BindingAdapter 사용법 (0) | 2022.09.12 |
[Android] 아이템 하나만 선택 가능한 리사이클러뷰 만드는 법 + 데이터바인딩 적용 (0) | 2022.08.25 |
[Android] 유튜브 라이브러리로 영상을 전체화면으로 재생하는 방법 + 리사이클러뷰에서 웹뷰로 여러 영상 재생하기 (0) | 2022.08.08 |
[Android] 코틀린으로 리사이클러뷰 클릭 이벤트 구현하는 방법 정리 (0) | 2022.08.08 |