Kotlin addTextChangeListener lambda?


109

Kotlin'de EditText addTextChangeListener için bir lambda ifadesini nasıl oluşturursunuz? Aşağıda bir hata veriyor:

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

3
Hangi hatayı veriyor?
voddan

Yanıtlar:


257

addTextChangedListener()TextWatcher3 yöntemli bir arayüz olan a'yı alır . Yazdıklarınız TextWatcheryalnızca 1 yöntemi olsaydı işe yarar . Aldığınız hatanın lambda'nızın diğer 2 yöntemi uygulamamasıyla ilgili olduğunu tahmin edeceğim. İleriye dönük 2 seçeneğiniz var.

  1. Lambdayı terk edin ve anonim bir iç sınıf kullanın
    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. Lambda ifadesi kullanabilmek için bir uzantı yöntemi oluşturun:
    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())
          }
        })
    }

Ve sonra uzantıyı şu şekilde kullanın:

editText.afterTextChanged { doSomethingWithText(it) }

4
Emin değilim kişisel tercih ya da daha iyi tarzı, ama Uzantınız fonksiyonu bir ifade gövdesine (dönüştürülebilir eğer fun foo() = ...)
F. George

7
@ mEQ5aNLrK3lqs3kfSa5HbvsTWe0nIu Dönüştürülebileceği konusunda haklısınız. Bununla birlikte, bir satırdan uzun işlevler için, işlevin nerede başladığını ve nerede durduğunu açıkça işaretlemek için çevreleyen parantezlere sahip olmayı seviyorum. Okunabilirliği artırdığına inanıyorum ama tamamen bir stil tercihi. Sanırım her iki şekilde de tartışılabilir :)
Andrew Orobator

2
İlgi dışı: Neden afterTextChanged.invoke(...)yerine arayasınız afterTextChanged(...)?
Felix D.

Bu benim için çalıştı. Yeniden kullanılabilirlik için 2. seçeneği tercih ettim.
Onie Maniego

24

Biraz eski, ancak Kotlin Android uzantılarını kullanarak şöyle bir şey yapabilirsiniz:

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

Ekstra koda gerek yok, sadece şunu ekleyin:

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

4
Android X'e yeniden düzenleme yaptıktan sonra bile bu benim için çalışmıyor. Neyi yanlış yapabileceğime dair herhangi bir tahmin var mı?
Nícolas Schirmer

3
Benim için de çalışmıyor. Görünüşe göre KTX artık bu uzantıyı sağlamıyor, ancak KAndroid çözüm mükemmel çalışıyor.
Igor Wojda


implementation "androidx.core:core-ktx:1.2.0"->edt.addTextChangedListener(afterTextChanged = { /*dosomething*/ })
Dr.jacky

24

Bu çekirdek ktx bağımlılığını ekleyin

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

Sadece yapmalısın

passwordEditText.doAfterTextChanged{ }


14

Dene :

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) {

    }

})

12

umarım bu Kotlinörnek netleşmeye yardımcı olur:

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
   }
}

Bu XMLdüzen ile:

<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>

Ve bu 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

10

eğer kullanırsan implementation 'androidx.core:core-ktx:1.1.0-alpha05'kullanabilirsin

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

Geç kaldığım için üzgünüm!

Eğer eklerseniz implementation 'androidx.core:core-ktx:1.1.0'sizin modülün build.gradle dosyasına o zaman kullanabilirsiniz

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

2

Diğer bir alternatif ise KAndroidkütüphane -

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

O zaman böyle bir şey yapabilirsin ...

editText.textWatcher { afterTextChanged { doSomething() } }

Açıkçası, sorununuzu çözmek için tüm bir kitaplığı kullanmak aşırıdır, ancak aynı zamanda Android SDK'daki standart kodu ortadan kaldıran bir dizi başka yararlı uzantı ile birlikte gelir.


2

Kotlin'in adlandırılmış parametrelerini kullanabilirsiniz:

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)
    }
})

1

Çekirdek ktx bağımlılığını ekleyin

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

Ve böyle basitçe uygulayabilirsiniz

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

-9

Bu harika görünüyor:

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

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

1
Sizi gerçekten bilmiyorum çocuklar ama cevabım benim için çalıştı ve yukarıdaki ve aşağıdaki cevaptan daha kısa ..
LEMUEL ADANE

1
Bu, kodun amaçladığı gibi çalışır, DONE düğmesine basıldığında eylemi gerçekleştirir. Koşulun dışına bir tost yerleştirerek kodu değiştirdim ve yalnızca TAB / DONE / etc tuşlarına basıldığında ateşleniyor gibi görünüyor. ama diğer karakterlerde değil.
Onie Maniego
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.