watcher studio eventos edittext addtextchangedlistener android textwatcher

android - studio - ¿Cómo usar Single TextWatcher para múltiples EditTexts?



textview watcher in android (11)

Implementación de MultiTextWatcher

public class MultiTextWatcher { private TextWatcherWithInstance callback; public MultiTextWatcher setCallback(TextWatcherWithInstance callback) { this.callback = callback; return this; } public MultiTextWatcher registerEditText(final EditText editText) { editText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { callback.beforeTextChanged(editText, s, start, count, after); } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { callback.onTextChanged(editText, s, start, before, count); } @Override public void afterTextChanged(Editable editable) { callback.afterTextChanged(editText, editable); } }); return this; } interface TextWatcherWithInstance { void beforeTextChanged(EditText editText, CharSequence s, int start, int count, int after); void onTextChanged(EditText editText, CharSequence s, int start, int before, int count); void afterTextChanged(EditText editText, Editable editable); } }

Uso

new MultiTextWatcher() .registerEditText(editText1) .registerEditText(editText2) .registerEditText(editText3) .setCallback(new TextWatcherWithInstance() { @Override public void beforeTextChanged(EditText editText, CharSequence s, int start, int count, int after) { // TODO: Do some thing with editText } @Override public void onTextChanged(EditText editText, CharSequence s, int start, int before, int count) { // TODO: Do some thing with editText } @Override public void afterTextChanged(EditText editText, Editable editable) { // TODO: Do some thing with editText } });

Tengo tres widgets de EditText en mi diseño de vista. ¿Hay alguna manera de usar un solo TextWatcher para los tres EditTexts ?


Acabo de encontrar este problema. Lo resolví creando una implementación de clase interna de TextWatcher que toma una Vista como argumento. Luego, en la implementación del método, simplemente encienda la vista para ver de cuál viene el Editable

Declaración:

private class GenericTextWatcher implements TextWatcher{ private View view; private GenericTextWatcher(View view) { this.view = view; } public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {} public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {} public void afterTextChanged(Editable editable) { String text = editable.toString(); switch(view.getId()){ case R.id.name: model.setName(text); break; case R.id.email: model.setEmail(text); break; case R.id.phone: model.setPhone(text); break; } } }

Uso:

name = (EditText) findViewById(R.id.name); name.setText(model.getName()); name.addTextChangedListener(new GenericTextWatcher(name)); email = (EditText) findViewById(R.id.email); email.setText(model.getEmail()); email.addTextChangedListener(new GenericTextWatcher(email)); phone = (EditText) findViewById(R.id.phone); phone.setText(model.getPhone()); phone.addTextChangedListener(new GenericTextWatcher(phone));


Así es como lo hice:

Cree una ArrayList de EditTexts, y luego use un ciclo for para aplicar TextWatcher para todos los EditTexts, si tiene un comportamiento para todos los editTexts, luego simplemente aplíquelo allí, si su comportamiento específico para algunos editTexts específicos, puede usar un if declaración para seleccionar y aplicar a editTexts individuales ... aquí está mi código:

ArrayList<EditText> editTexts = new ArrayList<>(); // Container list editText1 = (EditText) findViewById(R.id.editText1); editText2 = (EditText) findViewById(R.id.editText2); editText3 = (EditText) findViewById(R.id.editText3); editTexts.add(editText1); // editTexts[0] editTexts.add(editText2); // editTexts[1] editTexts.add(editText3); // editTexts[2] for (final EditText editText : editTexts) { //need to be final for custom behaviors editText.addTextChangedListener(new TextWatcher() { @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) { //Apply general behavior for all editTexts if (editText == editTexts.get(1)) { //Apply custom behavior just for this editText } } }); }

Espero que esto ayude


Funcionará con este código

TextWatcher watcher = new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { //YOUR CODE } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { //YOUR CODE } @Override public void afterTextChanged(Editable s) { String outputedText = s.toString(); mOutputText.setText(outputedText); } };

A continuación, agregue esto en oncreate

mInputText.addTextChangedListener(watcher); e2.addTextChangedListener(watcher); e3.addTextChangedListener(watcher); e4.addTextChangedListener(watcher);


Haga que su clase herede de Activity e implemente TextWatcher.

Luego, a través de la magia del polimorfismo, solo tienes que suscribirte a los eventos.

Esto no le indicará qué TextEdit cambió, sin embargo, si utiliza una combinación de esta y la respuesta de Sky Kelsey , podría resolverlo bien.

public YourActivity extends Activity implements TextWatcher { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_YourActivity); //Subscribe to the events EditText txt1 = (EditText) findViewById(R.id.txt1); txt1.addTextChangedListener(this); EditText txt2 = (EditText) findViewById(R.id.txt2); txt2.addTextChangedListener(this); } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { EditText txt1 = (EditText) findViewById(R.id.txt1); EditText txt2 = (EditText) findViewById(R.id.txt2); // You probably only want the text value from the EditText. But you get the idea. doStuff(txt1,txt2); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.calc, menu); return true; } @Override public void afterTextChanged(Editable s) { // TODO Auto-generated method stub } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { // TODO Auto-generated method stub } }


Sé que esta pregunta es antigua, sin embargo, quería compartir una de mi solución (en Kotlin). Mi solución es una mejora de la respuesta de @Shwarz Andrei, mi razón era qué pasaría si quisieras manipular más cosas / objetos.

En lugar de pasar la list of EditTexts y a Button como params, solo pasaría su list of editText . Luego dentro de tu clase personalizada implementarías una lambda como:

var hasFilled:((Boolean)->Unit)? = null

Luego lo configurará o lo elevará dentro de afterTextChanged

override fun afterTextChanged(p0: Editable?) { for (edit in _editTextList) { if (edit?.text.toString().trim().isEmpty()) { hasFilled?.invoke(false) //<-- here break } else { hasFilled?.invoke(true) //<--- here } } }

Entonces, cada vez que hay un cambio en EditText, se invoca su lambda

val editTexts = listOf(emailEditText,passwordEditText) // your list of editText val textWatcher = customTextWatcher(editTexts) // initialize your custom object editTexts.forEach { it -> it?.addTextChangedListener(textWatcher) } // each editText would listen for changes textWatcher.hasFilled = { value -> // now you have access to your lambda if (value != true) { // change the state of the button to unable // do other things } else { // change the state of the button to enable // do other things } }


Sé que este es un problema antiguo, y hay una decisión correcta. Escribiré los suyos, tal vez ayudará a alguien.

Emulando el ejemplo clásico donde tenemos N EditText, y queremos mostrar el botón si todos los campos están llenos. Este ejemplo tiene sentido, especialmente si usa validadores adicionales para cada uno.

Hice un ejemplo con respecto al problema, pero puedes hacer cualquier conjunto

MultiEditText.class

public class MultiEditText extends AppCompatActivity{ EditText ed_1, ed_2, ed_3; Button btn_ok; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.multi_edit_text); ed_1 = (EditText) findViewById(R.id.ed_1); ed_2 = (EditText) findViewById(R.id.ed_2); ed_3 = (EditText) findViewById(R.id.ed_3); btn_ok = (Button) findViewById(R.id.btn_ok); btn_ok.setEnabled(false); //if want more here can cycle interface List

EditText[] edList = {ed_1, ed_2, ed_3}; CustomTextWatcher textWatcher = new CustomTextWatcher(edList, btn_ok); for (EditText editText : edList) editText.addTextChangedListener(textWatcher);

} }

Parece muy simple, ahora

CustomTextWatcher.class

public class CustomTextWatcher implements TextWatcher { View v; EditText[] edList; public CustomTextWatcher(EditText[] edList, Button v) { this.v = v; this.edList = edList; } @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) { for (EditText editText : edList) { if (editText.getText().toString().trim().length() <= 0) { v.setEnabled(false); break; } else v.setEnabled(true); } } }

Agregaré un diseño, para que no pierdas el tiempo

multi_edit_text.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="16dp"> <EditText android:id="@+id/ed_1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_marginTop="8dp" /> <EditText android:id="@+id/ed_2" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/ed_1" android:layout_centerHorizontal="true" android:layout_marginTop="8dp" /> <EditText android:id="@+id/ed_3" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/ed_2" android:layout_centerHorizontal="true" android:layout_marginTop="8dp" /> <Button android:id="@+id/btn_ok" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/ed_3" android:layout_centerHorizontal="true" android:layout_marginTop="8dp" android:text="OK" /> </RelativeLayout>


Si desea usar solo editables después de la comparación de texto:

@Override public void afterTextChanged(Editable editable) { if (editable == mEditText1.getEditableText()) { // DO STH } else if (editable == mEditText2.getEditableText()) { // DO STH } }


Si desea utilizar el código hashChanged compare hashCode() mencionado a continuación -

@Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { if(charSequence.hashCode() == first_edit_text.getText().hashCode()){ // do other things } if(charSequence.hashCode() == second_edit_text.getText().hashCode()){ // do other things } }

O

Si desea utilizar AfterTextChanged compare Editable mencionado a continuación -

@Override public void afterTextChanged(Editable editable) { if (editable == first_edit_text.getEditableText()) { // do other things } else if (editable == second_edit_text.getEditableText()) { // do other things } }


TextWatcher watcher = new TextWatcher(){ @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { } @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { } @Override public void afterTextChanged(Editable editable) { } };

Entonces:

editText1.addTextChangedListener(watcher); editText2.addTextChangedListener(watcher); editText3.addTextChangedListener(watcher);


public class MainActivity extends AppCompatActivity{ EditText value1, value2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //instantiate EditText controls value1 = (EditText)findViewById(R.id.txtValue1); value2 = (EditText)findViewById(R.id.txtValue2); //set up text changed listener value1.addTextChangedListener(new TextChange(value1)); value2.addTextChangedListener(new TextChange(value2)); //inner class private class TextChange implements TextWatcher { /** * This method is called to notify you that, within <code>s</code>, * the <code>count</code> characters beginning at <code>start</code> * are about to be replaced by new text with length <code>after</code>. * It is an error to attempt to make changes to <code>s</code> from * this callback. * * @param s * @param start * @param count * @param after */ View view; private TextChange (View v) { view = v; }//end constructor @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } /** * This method is called to notify you that, within <code>s</code>, * the <code>count</code> characters beginning at <code>start</code> * have just replaced old text that had length <code>before</code>. * It is an error to attempt to make changes to <code>s</code> from * this callback. * * @param s * @param start * @param before * @param count */ @Override public void onTextChanged(CharSequence s, int start, int before, int count) { switch (view.getId()) { case R.id.txtValue1: //insert your TextChangedListener codes here break; case R.id.txtValue2: //insert your TextChangedListener codes here break; }//end switch }//end method onTextChanged }//end inner class TextChange }//end classMainActivity