Kotlin addTextChangeListener lambda?

如何为 Kotlin 的 EditText addTextChangeListener 构建一个 lambda 表达式:

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

addTextChangedListener()接受一个 TextWatcher,它是一个包含3个方法的接口。只有在 TextWatcher只有一个方法的情况下,您编写的代码才能正常工作。我猜你得到的错误与你的 lambda 没有实现其他两个方法有关。接下来你有两个选择。

  1. 抛弃 lambda,使用一个匿名内部类
    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 表达式:
    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) }

这看起来不错:

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


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

另一种选择是 KAndroid库-

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

然后你可以做这样的事情..。

editText.textWatcher { afterTextChanged { doSomething() } }

显然,使用整个库来解决您的问题是过分的,但是它还附带了一系列其他有用的扩展,这些扩展消除了 Android SDK 中的样板代码。

有点老,但是使用 Kotlin Android 扩展你可以做到这样:

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

不需要额外的代码,只需添加:

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

希望这个 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

如果你使用 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

您可以使用 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)
}
})

测试一下:

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

添加这个核心 ktx 依赖项

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

你只需要做

passwordEditText.doAfterTextChanged{ }

抱歉我迟到了!

如果将 implementation 'androidx.core:core-ktx:1.1.0'添加到模块的 build.gradle 文件中,那么可以使用

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

添加核心 ktx 依赖项

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

你可以像这样简单地实现

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

如果你正在使用材质 填充文本字段或者 概述文本字段,尝试分别响应文档中提到的输入文本的变化:

filledTextField.editText?.doOnTextChanged { inputText, _, _, _ ->
// Respond to input text change
}

还有

outlinedTextField.editText?.doOnTextChanged { inputText, _, _, _ ->
// Respond to input text change
}

这是带有 TextWatcher 编辑文本字段的 lambda 函数

searchField.addTextChangedListener(
afterTextChanged = {


},
onTextChanged = {s, start, before, count->
TODO("DO your code")
},
beforeTextChanged = {s, start, before, count->
TODO("DO your code")
}
)