Come utilizzare la classe TextWatcher in Android?


103

Qualcuno può dirmi come mascherare il sottostringa in EditTexto come cambiare EditText ingresso substring al tipo di password o di sostituirlo con un altro personaggio come questo 123xxxxxxxxx3455

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

Per favore, dimmi come posso usare il TextWatchermetodo su Android.

Risposte:


174

Per l'uso del 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
    }
});

59
cosa fare con questo TextWatcher? Fornisci maggiori dettagli per una migliore comprensione.
Paresh Mayani

Nel metodo che vengono sovrascritti per il text watcher. puoi mascherare il testo che volevi veramente.
Dinesh Prajapati

2
ma non so come usare TextWatcher, puoi spiegarlo con un piccolo esempio grazie per le tue linee guida
Sviluppatore Android

metti questo codice in java..non appena l'utente digita il testo verrà chiamato uno del metodo ... in base al nome della funzione.
Dinesh Prajapati

1
In realtà, se questo è il requisito, meglio non usare il testo watcher. Andrà in loop infinito
Dinesh Prajapati

119

L' TextWatcherinterfaccia ha 3 metodi di callback che vengono tutti chiamati nel seguente ordine quando si verifica una modifica al testo:

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

Chiamato prima che le modifiche siano state applicate al testo.
Il sparametro è il testo prima dell'applicazione di qualsiasi modifica.
Il startparametro è la posizione dell'inizio della parte modificata nel testo.
Il countparametro è la lunghezza della parte modificata nella ssequenza dalla startposizione.
E il afterparametro è la lunghezza della nuova sequenza che sostituirà la parte della ssequenza da starta start+count.
Non è necessario modificare il testo in TextViewda questo metodo (utilizzando myTextView.setText(String newText)).

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

Simile al beforeTextChangedmetodo ma chiamato dopo che il testo cambia.
Il sparametro è il testo dopo che le modifiche sono state applicate.
Il startparametro è lo stesso del beforeTextChangedmetodo.
Il countparametro è il afterparametro nel metodo beforeTextChanged.
E il beforeparametro è il countparametro nel metodo beforeTextChanged.
Non è necessario modificare il testo in TextViewda questo metodo (utilizzando myTextView.setText(String newText)).

afterTextChanged(Editable s)

È possibile modificare il testo in TextViewda questo metodo.
/! \ Attenzione: quando si modifica il testo in TextView, TextWatcherverrà attivato nuovamente, avviando un ciclo infinito. Dovresti quindi aggiungere come una boolean _ignoreproprietà che impedisce il ciclo infinito.
Esempio:

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

Sommario:

inserisci qui la descrizione dell'immagine


Una classe pronta per l'uso: TextViewListener

Personalmente, ho creato il mio listener di testo personalizzato, che mi dà le 4 parti in stringhe separate, il che è, per me, molto più intuitivo da usare.

 /**
   * 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;
    }
  }

Esempio:

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();
        }
}

Il problema con questo codice è che il cursore non rimane dove dovrebbe essere o almeno questa è stata la mia esperienza.
jonasxd360

È textview che chiama questi metodi

Suppongo di sì
Yairopro

risolto il problema con il cursore in questo modo: protected void onTextChanged (String before, String old, String aNew, String after, Editable sequence)
Eugene Strelnikov

49

Risposta supplementare

Ecco un supplemento visivo alle altre risposte. La mia risposta più completa con il codice e le spiegazioni è qui .

  • Rosso: testo che sta per essere cancellato (sostituito)
  • Verde: testo appena aggiunto (in sostituzione del vecchio testo rosso)

inserisci qui la descrizione dell'immagine


6

Utilizzo di TextWatcher in Android

Ecco un codice di esempio. Prova a utilizzare il addTextChangedListenermetodo di 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);
            }
        }
    });

5

Una prospettiva un po 'più grande della soluzione:

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

Questo funziona per me, lo faccio la prima volta.


5

Crea una sottoclasse TextWatcher personalizzata:

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);

    }
}

Imposta listener per il tuo EditText:

mTargetEditText.addTextChangedListener(new CustomWatcher());

Questo è in realtà un modo intelligente e leggero per risolvere il problema! Grazie!
FRR

2

Per Kotlin usa la funzione di estensione KTX : (usa TextWatchercome risposte precedenti)

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


importazione core-KTX:

implementation "androidx.core:core-ktx:1.2.0"

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

1

se si implementa con dialog edittext. utilizzare in questo modo :. è lo stesso con l'uso di altri testi editoriali.

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

    }
});

-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()));
      }

         });

Per ulteriori informazioni fare clic qui http://androiddhina.blogspot.in/2015/05/android-textwatcher.html

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.