Kotlin addTextChangeListener 람다?


104

Kotlin에서 EditText addTextChangeListener에 대한 람다 표현식을 어떻게 빌드하나요? 아래는 오류를 제공합니다.

passwordEditText.addTextChangedListener { charSequence  ->
    try {
        password = charSequence.toString()
    } catch (error: Throwable) {
        raise(error)
    }
}

2
어떤 오류가 발생합니까?
voddan

답변:


246

addTextChangedListener()얻어 TextWatcher3 방법에 대한 인터페이스를이다. 당신이 쓴 것은 TextWatcher오직 하나의 방법 만있는 경우에만 작동합니다 . 나는 당신이 얻는 오류가 다른 두 가지 방법을 구현하지 않는 람다와 관련이 있다고 추측 할 것입니다. 앞으로 두 가지 옵션이 있습니다.

  1. 람다를 버리고 익명의 내부 클래스를 사용하십시오.
    editText.addTextChangedListener(object : TextWatcher {
      override fun afterTextChanged(s: Editable?) {
      }
    
      override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
      }
    
      override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
      }
    })
  1. 람다 식을 사용할 수 있도록 확장 메서드를 만듭니다.
    fun EditText.afterTextChanged(afterTextChanged: (String) -> Unit) {
        this.addTextChangedListener(object : TextWatcher {
          override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
          }
    
          override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
          }
    
          override fun afterTextChanged(editable: Editable?) {
            afterTextChanged.invoke(editable.toString())
          }
        })
    }

그런 다음 확장을 다음과 같이 사용하십시오.

editText.afterTextChanged { doSomethingWithText(it) }

4
개인 취향이나 더 나은 스타일인지 확실하지 않지만 확장 기능을 표현 본문으로 변환 할 수 있습니다 ( fun foo() = ...)
F. George

6
@ mEQ5aNLrK3lqs3kfSa5HbvsTWe0nIu 변환 될 수 있다는 말이 맞습니다. 그러나 한 줄보다 긴 함수의 경우 함수가 시작되고 중지되는 위치를 명확하게 표시하기 위해 괄호를 둘러싸는 것이 좋습니다. 나는 그것이 가독성을 증가 시킨다고 생각하지만 그것은 완전히 스타일 선호입니다. 나는 두 가지 :) 주장 할 수 있다고 생각
앤드류 Orobator을

2
관심 없음 : afterTextChanged.invoke(...)대신 전화 하는 이유 는 afterTextChanged(...)무엇입니까?
Felix D.

이것은 나를 위해 일했습니다. 재사용 성을 위해 두 번째 옵션을 선호했습니다.
Onie Maniego

21

조금 오래되었지만 Kotlin Android 확장 프로그램을 사용하면 다음과 같이 할 수 있습니다.

editTextRequest.textChangedListener {
            afterTextChanged {
                // Do something here...
            }
}

추가 코드가 필요하지 않으며 다음을 추가하십시오.

implementation 'androidx.core:core-ktx:1.0.0'

4
Android X로 리팩토링 한 후에도 작동하지 않습니다. 내가 뭘 잘못하고 있는지 추측 할 수 있나요?
Nícolas Schirmer

3
나에게도 효과가 없습니다. KTX가 더 이상이 확장을 제공하지 않는 것 같지만 KAndroid 솔루션은 완벽하게 작동합니다.
Igor Wojda


17

이 핵심 ktx 종속성 추가

implementation 'androidx.core:core-ktx:1.0.0'

당신은 단순히해야

passwordEditText.doAfterTextChanged{ }


12

Kotlin샘플 이 이를 명확히하는 데 도움 이되기를 바랍니다 .

class MainFragment : Fragment() {

    private lateinit var viewModel: MainViewModel

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                          savedInstanceState: Bundle?): View {
    val view = inflater.inflate(R.layout.main_fragment, container, false)

    view.user.addTextChangedListener(object : TextWatcher {
        override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {

        }

        override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {

        }

        override fun afterTextChanged(s: Editable) {
                userLayout.error =
                        if (s.length > userLayout.counterMaxLength) {
                            "Max character length is: ${userLayout.counterMaxLength}"
                        } else null
        }
    })
    return view
}

override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)
    viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
    // TODO: Use the ViewModel
   }
}

XML레이아웃으로 :

<android.support.design.widget.TextInputLayout
    android:id="@+id/userLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:counterMaxLength="5"
    app:counterEnabled="true"
    android:hint="user_name">

    <android.support.design.widget.TextInputEditText
        android:id="@+id/user"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</android.support.design.widget.TextInputLayout>

그리고 이것은 Gradle:

android {
    compileSdkVersion 'android-P'
...
}
    api 'com.android.support:design:28.0.0-alpha1'

    implementation 'com.android.support:appcompat-v7:28.0.0-alpha1' // appcompat library

12

그것을 테스트하십시오 :

passwordEditText.addTextChangedListener(object:TextWatcher{override fun afterTextChanged(s: Editable?) {

    }

    override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
    }

    override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {

    }

})

10

사용 implementation 'androidx.core:core-ktx:1.1.0-alpha05'하면 사용할 수 있습니다

For android.widget.TextView
TextWatcher 
TextView.doBeforeTextChanged(crossinline action: (text: CharSequence?, start: Int, count: Int, after: Int) -> Unit)
Add an action which will be invoked before the text changed.

TextWatcher 
TextView.doOnTextChanged(crossinline action: (text: CharSequence?, start: Int, count: Int, after: Int) -> Unit)
Add an action which will be invoked when the text is changing.

TextWatcher 
TextView.doAfterTextChanged(crossinline action: (text: Editable?) -> Unit)

https://developer.android.com/reference/kotlin/androidx/core/widget/package-summary#extension-functions


4

늦어서 죄송합니다!

implementation 'androidx.core:core-ktx:1.1.0'모듈의 build.gradle 파일에 추가 하면 다음을 사용할 수 있습니다.

etPlayer1.doOnTextChanged { text, start, count, after -> // Do stuff }

2

또 다른 대안은 KAndroid도서관입니다.

implementation 'com.pawegio.kandroid:kandroid:0.8.7@aar'

그러면 이렇게 할 수 있습니다 ...

editText.textWatcher { afterTextChanged { doSomething() } }

분명히 전체 라이브러리를 사용하여 문제를 해결하는 것은 과도하지만 Android SDK에서 상용구 코드를 제거하는 다른 유용한 확장 기능도 제공됩니다.


2

kotlin의 명명 된 매개 변수를 사용할 수 있습니다.

private val beforeTextChangedStub: (CharSequence, Int, Int, Int) -> Unit = { _, _, _, _ -> }
private val onTextChangedStub: (CharSequence, Int, Int, Int) -> Unit = { _, _, _, _ -> }
private val afterTextChangedStub: (Editable) -> Unit = {}

fun EditText.addChangedListener(
        beforeTextChanged: (CharSequence, Int, Int, Int) -> Unit = beforeTextChangedStub,
        onTextChanged: (CharSequence, Int, Int, Int) -> Unit = onTextChangedStub,
        afterTextChanged: (Editable) -> Unit = afterTextChangedStub
) = addTextChangedListener(object : TextWatcher {
    override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {
        beforeTextChanged(charSequence, i, i1, i2)
    }

    override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {
        onTextChanged(charSequence, i, i1, i2)
    }

    override fun afterTextChanged(editable: Editable) {
        afterTextChanged(editable)
    }
})

0

핵심 ktx 종속성 추가

implementation 'androidx.core:core-ktx:1.3.0'

다음과 같이 간단히 구현할 수 있습니다.

    edit_text.addTextChangedListener { it: Editable? ->
      // Do your stuff here
    }

-9

이것은 깔끔해 보입니다.

passwordEditText.setOnEditorActionListener { 
    textView, keyCode, keyEvent ->
    val DONE = 6

    if (keyCode == DONE) {                       
         // your code here
    }
    false
}

1
나는 너희들과 정말 잘 모르겠지만 내 대답은 나를 위해 일했으며 위와 아래의 대답보다 짧습니다 ..
LEMUEL ADANE

1
이것은 코드가 의도 한대로 작동하며 DONE을 누르면 작업을 수행합니다. 조건 외부에 토스트를 배치하여 코드를 수정했는데 TAB / DONE / etc를 누를 때만 실행되는 것 같습니다. 하지만 다른 캐릭터에는 없습니다.
Onie Maniego
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.