Comment construisez-vous une expression lambda pour EditText addTextChangeListener dans Kotlin? Ci-dessous donne une erreur:
passwordEditText.addTextChangedListener { charSequence ->
try {
password = charSequence.toString()
} catch (error: Throwable) {
raise(error)
}
}
addTextChangedListener()
prend un TextWatcher
qui est une interface avec 3 méthodes. Ce que vous avez écrit ne fonctionnerait que si TextWatcher
n'avait qu'une seule méthode. Je vais deviner que l'erreur que vous obtenez concerne le fait que votre lambda n'implémente pas les 2 autres méthodes. Vous avez 2 options pour aller de l'avant.
1) Fossé le lambda et juste utiliser une classe intérieure anonyme
editText.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(p0: Editable?) {
}
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
})
2) Créez une méthode d’extension pour pouvoir utiliser une expression lambda:
fun EditText.afterTextChanged(afterTextChanged: (String) -> Unit) {
this.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun afterTextChanged(editable: Editable?) {
afterTextChanged.invoke(editable.toString())
}
})
}
Et utilisez ensuite l'extension comme ceci:
editText.afterTextChanged { doSomethingWithText(it) }
espérons que cet exemple Kotlin
aidera à bien comprendre:
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
}
}
Avec cette mise en page 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>
Et ceci 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
Un peu vieux, mais en utilisant les extensions Kotlin Android, vous pouvez faire quelque chose comme ça:
editTextRequest.textChangedListener {
afterTextChanged {
// Do something here...
}
}
Aucun code supplémentaire nécessaire, ajoutez simplement:
implementation 'androidx.core:core-ktx:1.0.0'
si vous utilisez implementation 'androidx.core:core-ktx:1.1.0-alpha05'
vous pouvez utiliser
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)
Essaye-le :
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) {
}
})
Une autre alternative est la bibliothèque KAndroid
-
implementation 'com.pawegio.kandroid:kandroid:0.8.7@aar'
Ensuite, vous pourriez faire quelque chose comme ça ...
editText.textWatcher { afterTextChanged { doSomething() } }
Évidemment, il est excessif d’utiliser une bibliothèque entière pour résoudre votre problème, mais il est également livré avec une série d’extensions utiles qui éliminent le code standard dans le SDK Android.
Vous pouvez utiliser les paramètres nommés de 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)
}
})