layouts framework extensions android kotlin textview android-textview anko

extensions - framework android kotlin



KOTLIN addTextChangeListener lambda? (8)

Espero que esta muestra de Kotlin ayude a dejar en claro:

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

Con este diseño 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>

Y este 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

¿Cómo se construye una expresión lambda para EditText addTextChangeListener en Kotlin? A continuación se muestra un error:

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


Esto se ve bien:

passwordEditText.setOnEditorActionListener { textView, keyCode, keyEvent -> val DONE = 6 if (keyCode == DONE) { // your code here } false }


Otra alternativa es la biblioteca KAndroid :

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

Entonces podrías hacer algo como esto ...

editText.textWatcher { afterTextChanged { doSomething() } }

Obviamente, es excesivo usar una biblioteca completa para resolver su problema, pero también viene con una gama de otras extensiones útiles que eliminan el código repetitivo en el SDK de Android.


Pruébalo :

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


Puede hacer uso de los parámetros con nombre 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) } })


Un poco viejo, pero usando las extensiones de Android Kotlin puedes hacer algo así:

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

No se necesita código adicional, solo agregue:

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


si usa la implementation ''androidx.core:core-ktx:1.1.0-alpha05'' puede usar

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)

developer.android.com/reference/kotlin/androidx/core/widget/…


addTextChangedListener() toma un TextWatcher que es una interfaz con 3 métodos. Lo que escribiste solo funcionaría si TextWatcher tuviera solo 1 método. Voy a adivinar que el error que obtienes se relaciona con tu lambda que no implementa los otros 2 métodos. Tienes 2 opciones en el futuro.

1) Deshazte de la lambda y solo usa una clase interna anónima

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) Cree un método de extensión para que pueda usar una expresión 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()) } }) }

Y luego usa la extensión así:

editText.afterTextChanged { doSomethingWithText(it) }