Kotlin addTextChangeListener lambda?
Как построить лямбда-выражение для addTextChangeListener EditText в Kotlin? Ниже выдает ошибку:
passwordEditText.addTextChangedListener { charSequence ->
try {
password = charSequence.toString()
} catch (error: Throwable) {
raise(error)
}
}
14 ответов
Это выглядит аккуратно:
passwordEditText.setOnEditorActionListener {
textView, keyCode, keyEvent ->
val DONE = 6
if (keyCode == DONE) {
// your code here
}
false
}
addTextChangedListener()
занимает TextWatcher
который является интерфейсом с 3 методами. То, что вы написали, будет работать, только если 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) }
Добавьте эту базовую зависимость ktx
implementation 'androidx.core:core-ktx:1.0.0'
Вам просто нужно сделать
passwordEditText.doAfterTextChanged{ }
Немного устаревший, но используя расширения Kotlin для Android, вы можете сделать что-то вроде этого:
editTextRequest.textChangedListener {
afterTextChanged {
// Do something here...
}
}
Дополнительный код не требуется, просто добавьте:
implementation 'androidx.core:core-ktx:1.0.0'
Извините за опоздание!
Если вы добавите implementation 'androidx.core:core-ktx:1.1.0'
в файл build.gradle вашего модуля, вы можете использовать
etPlayer1.doOnTextChanged { text, start, count, after -> // Do stuff }
Попробуй это:
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) {
}
})
Надеюсь это 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
Если вы используете текстовое поле с заполненным материалом или текстовое поле с контуром , попытайтесь отреагировать на изменение вводимого текста , как указано в документации, соответственно:
filledTextField.editText?.doOnTextChanged { inputText, _, _, _ ->
// Respond to input text change
}
и
outlinedTextField.editText?.doOnTextChanged { inputText, _, _, _ ->
// Respond to input text change
}
Если вы используете 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
Добавить основную зависимость ktx
implementation 'androidx.core:core-ktx:1.3.0'
И вы можете просто реализовать вот так
edit_text.addTextChangedListener { it: Editable? ->
// Do your stuff here
}
Это лямбда-функция с текстовым полем редактирования с TextWatcher.
searchField.addTextChangedListener(
afterTextChanged = {
},
onTextChanged = {s, start, before, count->
TODO("DO your code")
},
beforeTextChanged = {s, start, before, count->
TODO("DO your code")
}
)
Вы можете использовать именованные параметры 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)
}
})
Другой альтернативой является KAndroid
библиотека -
implementation 'com.pawegio.kandroid:kandroid:0.8.7@aar'
Тогда вы могли бы сделать что-то вроде этого...
editText.textWatcher { afterTextChanged { doSomething() } }
Очевидно, что для решения вашей проблемы чрезмерно использовать целую библиотеку, но она также поставляется с рядом других полезных расширений, которые устраняют шаблонный код в Android SDK.
Несколько примеров:
Rx
RxTextView
.afterTextChangeEvents(editText)
.subscribe { presenter.onTextChanged(it.editable().toString())}
Это круто сделать что-то подобное
RxTextView
.afterTextChangeEvents(editText)
.skipInitialValue()
.debounce(500L, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe { presenter.onTextChanged(it.editable().toString())}
.autoDispose()
У меня есть пыльный класс, но вы можете легко его изменить (или нет)
public class SimpleTextWatcher implements TextWatcher {
private CallBackAfterTextChanged callBackAfterTextChanged;
public interface CallBackAfterTextChanged {
void afterTextChanged(Editable s);
}
public SimpleTextWatcher(CallBackAfterTextChanged callBackAfterTextChanged) {
this.callBackAfterTextChanged = callBackAfterTextChanged;
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {}
@Override
public void afterTextChanged(Editable s) {
callBackAfterTextChanged.afterTextChanged(s);
}
}
в Котлине
editSearch.addTextChangedListener(SimpleTextWatcher{ presenter.onTextChanged(it.toString())})
или расширение, но я не буду повторяться