KotlinでEditText addTextChangeListenerのラムダ式を作成するにはどうすればよいですか?以下にエラーを示します。
passwordEditText.addTextChangedListener { charSequence ->
try {
password = charSequence.toString()
} catch (error: Throwable) {
raise(error)
}
}
addTextChangedListener()
は、3つのメソッドを持つインターフェースである TextWatcher
を取ります。あなたが書いたものはTextWatcher
にメソッドが1つしかない場合にのみ機能します。取得しているエラーは、ラムダが他の2つのメソッドを実装していないことに関連していると推測します。今後2つのオプションがあります。
1)ラムダを捨てて、匿名の内部クラスを使用する
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)ラムダ式を使用できるように、拡張メソッドを作成します。
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) }
この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
少し古いですが、Kotlin Android拡張機能を使用すると、次のようなことができます。
editTextRequest.textChangedListener {
afterTextChanged {
// Do something here...
}
}
追加のコードは必要ありません。追加するだけです:
implementation 'androidx.core:core-ktx:1.0.0'
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)
試して :
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) {
}
})
別の代替手段はKAndroid
ライブラリです-
implementation 'com.pawegio.kandroid:kandroid:0.8.7@aar'
次に、このようなことをすることができます...
editText.textWatcher { afterTextChanged { doSomething() } }
ライブラリ全体を使用して問題を解決することは明らかに過剰ですが、Android SDKの定型コードを排除するその他の便利な拡張機能も付属しています。
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)
}
})