¿Cómo usar la clase TextWatcher en Android?

103

¿Puede alguien decirme cómo enmascarar la subcadena en EditTexto cómo cambiar EditText la entrada subcadena que introduzca la contraseña o sustituir por otro personaje como éste 123xxxxxxxxx3455

 String contents = et1.getText().toString();
 et1.setText(contents.replace.substring(0, contents.length()-2),"*");

Por favor, dígame cómo puedo usar el TextWatchermétodo en Android.

desarrollador de Android
fuente

Respuestas:

174

Para el uso de TextWatcher...

et1.addTextChangedListener(new TextWatcher() {
    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {

        // TODO Auto-generated method stub
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        // TODO Auto-generated method stub
    }

    @Override
    public void afterTextChanged(Editable s) {

        // TODO Auto-generated method stub
    }
});
Dinesh Prajapati
fuente
59
¿Qué hacer con este TextWatcher? Proporcione más detalles para una mejor comprensión.
Paresh Mayani
En el método que se anula para el observador de texto. puede enmascarar el texto que realmente deseaba.
Dinesh Prajapati
2
pero no sé cómo usar TextWatcher, ¿puedes explicarlo con un pequeño ejemplo? Gracias por tus pautas
desarrollador de Android
poner este código en java .. tan pronto como el usuario escriba el texto, se llamará a uno de los métodos ... de acuerdo con el nombre de la función.
Dinesh Prajapati
1
En realidad, si este es el requisito, entonces es mejor no usar el observador de texto. Va a un ciclo infinito
Dinesh Prajapati
119

La TextWatcherinterfaz tiene 3 métodos de devolución de llamada que se llaman en el siguiente orden cuando se produce un cambio en el texto:

beforeTextChanged(CharSequence s, int start, int count, int after)

Se llama antes de que los cambios se hayan aplicado al texto.
El sparámetro es el texto antes de que se aplique cualquier cambio.
El startparámetro es la posición del comienzo de la parte modificada en el texto.
El countparámetro es la longitud de la parte cambiada en la ssecuencia desde la startposición.
Y el afterparámetro es la longitud de la nueva secuencia que reemplazará la parte de la ssecuencia de starta start+count.
No debe cambiar el texto en el TextViewde este método (usando myTextView.setText(String newText)).

onTextChanged(CharSequence s, int start, int before, int count)

Similar al beforeTextChangedmétodo pero llamado después de que cambia el texto.
El sparámetro es el texto después de que se hayan aplicado los cambios.
El startparámetro es el mismo que en el beforeTextChangedmétodo.
El countparámetro es el afterparámetro del método beforeTextChanged.
Y el beforeparámetro es el countparámetro en el método beforeTextChanged.
No debe cambiar el texto en el TextViewde este método (usando myTextView.setText(String newText)).

afterTextChanged(Editable s)

Puede cambiar el texto TextViewde este método.
/! \ Advertencia: Cuando cambie el texto en TextView, el TextWatcherse activará nuevamente, iniciando un ciclo infinito. Luego debe agregar una boolean _ignorepropiedad similar que evite el bucle infinito.
Ejemplo:

new TextWatcher() {
        boolean _ignore = false; // indicates if the change was made by the TextWatcher itself.

        @Override
        public void afterTextChanged(Editable s) {
            if (_ignore)
                return;

            _ignore = true; // prevent infinite loop
            // Change your text here.
            // myTextView.setText(myNewText);
            _ignore = false; // release, so the TextWatcher start to listen again.
        }

        // Other methods...
    }

Resumen:

ingrese la descripción de la imagen aquí


Una clase lista para usar: TextViewListener

Personalmente, hice mi oyente de texto personalizado, que me da las 4 partes en cadenas separadas, lo cual es, para mí, mucho más intuitivo de usar.

 /**
   * Text view listener which splits the update text event in four parts:
   * <ul>
   *     <li>The text placed <b>before</b> the updated part.</li>
   *     <li>The <b>old</b> text in the updated part.</li>
   *     <li>The <b>new</b> text in the updated part.</li>
   *     <li>The text placed <b>after</b> the updated part.</li>
   * </ul>
   * Created by Jeremy B.
   */

  public abstract class TextViewListener implements TextWatcher {
    /**
     * Unchanged sequence which is placed before the updated sequence.
     */
    private String _before;

    /**
     * Updated sequence before the update.
     */
    private String _old;

    /**
     * Updated sequence after the update.
     */
    private String _new;

    /**
     * Unchanged sequence which is placed after the updated sequence.
     */
    private String _after;

    /**
     * Indicates when changes are made from within the listener, should be omitted.
     */
    private boolean _ignore = false;

    @Override
    public void beforeTextChanged(CharSequence sequence, int start, int count, int after) {
        _before = sequence.subSequence(0,start).toString();
        _old = sequence.subSequence(start, start+count).toString();
        _after = sequence.subSequence(start+count, sequence.length()).toString();
    }

    @Override
    public void onTextChanged(CharSequence sequence, int start, int before, int count) {
        _new = sequence.subSequence(start, start+count).toString();
    }

    @Override
    public void afterTextChanged(Editable sequence) {
        if (_ignore)
            return;

        onTextChanged(_before, _old, _new, _after);
    }

    /**
     * Triggered method when the text in the text view has changed.
     * <br/>
     * You can apply changes to the text view from this method
     * with the condition to call {@link #startUpdates()} before any update,
     * and to call {@link #endUpdates()} after them.
     *
     * @param before Unchanged part of the text placed before the updated part.
     * @param old Old updated part of the text.
     * @param aNew New updated part of the text?
     * @param after Unchanged part of the text placed after the updated part.
     */
    protected abstract void onTextChanged(String before, String old, String aNew, String after);

    /**
     * Call this method when you start to update the text view, so it stops listening to it and then prevent an infinite loop.
     * @see #endUpdates()
     */
    protected void startUpdates(){
        _ignore = true;
    }

    /**
     * Call this method when you finished to update the text view in order to restart to listen to it.
     * @see #startUpdates()
     */
    protected void endUpdates(){
        _ignore = false;
    }
  }

Ejemplo:

myEditText.addTextChangedListener(new TextViewListener() {
        @Override
        protected void onTextChanged(String before, String old, String aNew, String after) {
           // intuitive usation of parametters
           String completeOldText = before + old + after;
           String completeNewText = before + aNew + after;

           // update TextView
            startUpdates(); // to prevent infinite loop.
            myEditText.setText(myNewText);
            endUpdates();
        }
}
Yairopro
fuente
El problema con este código es que el cursor no permanece donde se supone que debe estar o al menos esa ha sido mi experiencia.
jonasxd360
¿Es textview el que llama a estos métodos
Supongo que sí
Yairopro
Se solucionó el problema con el cursor de esta manera: protected void onTextChanged (String before, String old, String aNew, String after, Editable sequence)
Eugene Strelnikov
49

Respuesta suplementaria

Aquí hay un complemento visual de las otras respuestas. Mi respuesta más completa con el código y las explicaciones está aquí .

  • Rojo: texto a punto de ser eliminado (reemplazado)
  • Verde: texto que se acaba de agregar (reemplazando el antiguo texto rojo)

ingrese la descripción de la imagen aquí

Suragch
fuente
6

Usando TextWatcher en Android

Aquí hay un código de muestra. Intente usar el addTextChangedListenermétodo de TextView

addTextChangedListener(new TextWatcher() {

        BigDecimal previousValue;
        BigDecimal currentValue;

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int
                count) {
            if (isFirstTimeChange) {
                return;
            }
            if (s.toString().length() > 0) {
                try {
                    currentValue = new BigDecimal(s.toString().replace(".", "").replace(',', '.'));
                } catch (Exception e) {
                    currentValue = new BigDecimal(0);
                }
            }
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count,
                int after) {
            if (isFirstTimeChange) {
                return;
            }
            if (s.toString().length() > 0) {
                try {
                    previousValue = new BigDecimal(s.toString().replace(".", "").replace(',', '.'));
                } catch (Exception e) {
                    previousValue = new BigDecimal(0);
                }
            }
        }

        @Override
        public void afterTextChanged(Editable editable) {
            if (isFirstTimeChange) {
                isFirstTimeChange = false;
                return;
            }
            if (currentValue != null && previousValue != null) {
                if ((currentValue.compareTo(previousValue) > 0)) {
                    //setBackgroundResource(R.color.devises_overview_color_green);
                    setBackgroundColor(flashOnColor);
                } else if ((currentValue.compareTo(previousValue) < 0)) {
                    //setBackgroundResource(R.color.devises_overview_color_red);

                    setBackgroundColor(flashOffColor);
                } else {
                    //setBackgroundColor(textColor);
                }
                handler.removeCallbacks(runnable);
                handler.postDelayed(runnable, 1000);
            }
        }
    });
Anandu
fuente
5

Una perspectiva un poco más amplia de la solución:

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.yourlayout, container, false);
        View tv = v.findViewById(R.id.et1);
        ((TextView) tv).addTextChangedListener(new TextWatcher() {
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                 SpannableString contentText = new SpannableString(((TextView) tv).getText());
                 String contents = Html.toHtml(contentText).toString();
            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

                // TODO Auto-generated method stub
            }

            @Override
            public void afterTextChanged(Editable s) {

                // TODO Auto-generated method stub
            }
        });
        return v;
    }

Esto funciona para mí, lo hago por primera vez.

Berit Larsen
fuente
5

Cree una subclase personalizada de TextWatcher:

public class CustomWatcher implements TextWatcher {

    private boolean mWasEdited = false;

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

        if (mWasEdited){

            mWasEdited = false;
            return;
        }

        // get entered value (if required)
        String enteredValue  = s.toString();

        String newValue = "new value";

        // don't get trap into infinite loop
        mWasEdited = true;
        // just replace entered value with whatever you want
        s.replace(0, s.length(), newValue);

    }
}

Establecer oyente para su EditText:

mTargetEditText.addTextChangedListener(new CustomWatcher());
Denis
fuente
¡Esta es en realidad una forma inteligente y liviana de resolver el problema! ¡Gracias!
FRR
2

Para Kotlin use la función de extensión KTX : (Se usa TextWatchercomo respuestas anteriores)

yourEditText.doOnTextChanged { text, start, count, after -> 
        // action which will be invoked when the text is changing
    }


importar core-KTX:

implementation "androidx.core:core-ktx:1.2.0"
Francis
fuente
1
    public class Test extends AppCompatActivity {

    EditText firstEditText;
    EditText secondEditText;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.test);
        firstEditText = (EditText)findViewById(R.id.firstEditText);
        secondEditText = (EditText)findViewById(R.id.secondEditText);

        firstEditText.addTextChangedListener(new EditTextListener());

    }

    private class EditTextListener implements 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) {
            secondEditText.setText(firstEditText.getText());
        }

        @Override
        public void afterTextChanged(Editable s) {
        }
    }
}
Ajay Shrestha
fuente
1

si implementa con el diálogo edittext. utilizar así :. es lo mismo con el uso de otro texto de edición.

dialog.getInputEditText().addTextChangedListener(new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence charSequence, int start, int before, int count) {
    }

    @Override
    public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
        if (start<2){
                dialog.getActionButton(DialogAction.POSITIVE).setEnabled(false);
            }else{
                double size =  Double.parseDouble(charSequence.toString());
                if (size > 0.000001 && size < 0.999999){
                    dialog.getActionButton(DialogAction.POSITIVE).setEnabled(true);
                }else{
                    ToastHelper.show(HistoryActivity.this, "Size must between 0.1 - 0.9");
                    dialog.getActionButton(DialogAction.POSITIVE).setEnabled(false);
                }

            }
    }

    @Override
    public void afterTextChanged(Editable editable) {

    }
});
Izzamed
fuente
-2
editext1.addTextChangedListener(new TextWatcher() {

   @Override
    public void onTextChanged(CharSequence s, int start, int before,
    int count) {
     editext2.setText(new String(s.toString()));

          }

   @Override
     public void beforeTextChanged(CharSequence s, int start, int count,
      int after) {

         editext2.setText(new String(s.toString()));
        }

      @Override
          public void afterTextChanged(Editable s) {

          editext2.setText(new String(s.toString()));
      }

         });

Para obtener más referencias, haga clic aquí http://androiddhina.blogspot.in/2015/05/android-textwatcher.html

Dhina k
fuente