如何在Kotlin中为EditText addTextChangeListener构建lambda表达式?下面给出了一个错误:
passwordEditText.addTextChangedListener { charSequence ->
try {
password = charSequence.toString()
} catch (error: Throwable) {
raise(error)
}
}
答案 0 :(得分:156)
addTextChangedListener()
需要一个TextWatcher
,这是一个有3种方法的接口。您编写的内容仅在TextWatcher
只有1个方法时才有效。我将猜测你所遇到的与你的lambda有关的错误没有实现其他两种方法。你有2个选择。
1)抛弃lambda并使用匿名内部类
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)创建一个扩展方法,以便您可以使用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())
}
})
}
然后像这样使用扩展名:
editText.afterTextChanged { doSomethingWithText(it) }
答案 1 :(得分:9)
希望此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
答案 2 :(得分:6)
有点旧,但使用Kotlin Android扩展程序,你可以做类似的事情:
editTextRequest.textChangedListener {
afterTextChanged {
// Do something here...
}
}
无需额外代码,只需添加:
implementation 'androidx.core:core-ktx:1.0.0'
答案 3 :(得分:5)
很抱歉迟到了!
如果您将implementation 'androidx.core:core-ktx:1.1.0'
添加到模块的build.gradle文件中,则可以使用
etPlayer1.doOnTextChanged { text, start, count, after -> // Do stuff }
答案 4 :(得分:3)
添加核心ktx依赖项
implementation 'androidx.core:core-ktx:1.3.0'
您可以像这样简单地实现
edit_text.addTextChangedListener { it: Editable? ->
// Do your stuff here
}
答案 5 :(得分:2)
添加此核心ktx依赖项
implementation 'androidx.core:core-ktx:1.0.0'
您只需要做
passwordEditText.doAfterTextChanged{ }
答案 6 :(得分:2)
如果您使用的是 Material Filled text field 或 Outlined text field,请分别尝试响应文档中提到的输入文本更改:
filledTextField.editText?.doOnTextChanged { inputText, _, _, _ ->
// Respond to input text change
}
和
outlinedTextField.editText?.doOnTextChanged { inputText, _, _, _ ->
// Respond to input text change
}
答案 7 :(得分:1)
另一种选择是KAndroid
库 -
implementation 'com.pawegio.kandroid:kandroid:0.8.7@aar'
然后你可以做这样的事情......
editText.textWatcher { afterTextChanged { doSomething() } }
显然,使用整个库来解决您的问题是过分的,但它还附带了一系列其他有用的扩展,可以消除Android SDK中的样板代码。
答案 8 :(得分:1)
如果您使用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)
答案 9 :(得分:0)
您可以使用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)
}
})
答案 10 :(得分:0)
测试:
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) {
}
})
答案 11 :(得分:-6)
这看起来很整洁:
passwordEditText.setOnEditorActionListener {
textView, keyCode, keyEvent ->
val DONE = 6
if (keyCode == DONE) {
// your code here
}
false
}