Como usar a classe TextWatcher no Android?

103

Alguém pode me dizer como para mascarar o substring em EditTextou como mudar EditText a entrada substring ao tipo de senha ou substituir por um outro personagem como este 123xxxxxxxxx3455

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

Por favor, me diga como posso usar o TextWatchermétodo no Android.

Desenvolvedor Android
fonte

Respostas:

174

Para uso do 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
fonte
59
o que fazer com este TextWatcher? Forneça mais detalhes para melhor compreensão.
Paresh Mayani
No método que são substituídos pelo observador de texto. você pode mascarar o texto que você realmente queria.
Dinesh Prajapati
2
mas eu não sei como usar o TextWatcher, posso explicar com um pequeno exemplo, obrigado por suas diretrizes
Desenvolvedor Android
coloque este código em java .. assim que o usuário digitar o texto um dos métodos será chamado ... de acordo com o nome da função.
Dinesh Prajapati
1
Na verdade, se esse for o requisito, é melhor não usar o observador de texto. Ele vai para um loop infinito
Dinesh Prajapati
119

A TextWatcherinterface possui 3 métodos de retorno de chamada que são todos chamados na seguinte ordem quando ocorre uma alteração no texto:

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

Chamado antes de as alterações serem aplicadas ao texto.
O sparâmetro é o texto antes de qualquer alteração ser aplicada.
O startparâmetro é a posição do início da parte alterada no texto.
O countparâmetro é o comprimento da parte alterada na ssequência desde a startposição.
E o afterparâmetro é o comprimento da nova sequência que substituirá a parte da ssequência de starta start+count.
Você não deve alterar o texto TextViewneste método (usando myTextView.setText(String newText)).

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

Semelhante ao beforeTextChangedmétodo, mas chamado após as alterações do texto.
O sparâmetro é o texto após a aplicação das alterações.
O startparâmetro é o mesmo do beforeTextChangedmétodo.
O countparâmetro é o afterparâmetro no método beforeTextChanged.
E o beforeparâmetro é o countparâmetro no método beforeTextChanged.
Você não deve alterar o texto TextViewneste método (usando myTextView.setText(String newText)).

afterTextChanged(Editable s)

Você pode alterar o texto em a TextViewpartir deste método.
/! \ Aviso: Ao alterar o texto no TextView, o TextWatcherserá acionado novamente, iniciando um loop infinito. Você deve então adicionar como uma boolean _ignorepropriedade que evita o loop infinito.
Exemplo:

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

Resumo:

insira a descrição da imagem aqui


Uma aula pronta para usar: TextViewListener

Pessoalmente, criei meu ouvinte de texto personalizado, o que me dá as 4 partes em strings separadas, o que é, para mim, muito mais 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;
    }
  }

Exemplo:

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
fonte
O problema com esse código é que o cursor não fica onde deveria estar ou pelo menos essa foi minha experiência.
jonasxd360
É o textview que chama esses métodos
Suponho que sim
Yairopro
corrigido o problema com o cursor desta forma: protected void onTextChanged (String antes, String antiga, String aNew, String depois, Sequência editável)
Eugene Strelnikov
49

Resposta complementar

Aqui está um suplemento visual para as outras respostas. Minha resposta mais completa com o código e as explicações está aqui .

  • Vermelho: texto prestes a ser excluído (substituído)
  • Verde: texto que acabou de ser adicionado (substituindo o antigo texto em vermelho)

insira a descrição da imagem aqui

Suragch
fonte
6

Usando TextWatcher no Android

Aqui está um código de amostra. Tente usar o 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
fonte
5

Perspectiva um pouco maior da solução:

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

Isso funciona para mim, na minha primeira vez.

Berit Larsen
fonte
5

Crie uma subclasse TextWatcher personalizada:

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

    }
}

Defina o ouvinte para seu EditText:

mTargetEditText.addTextChangedListener(new CustomWatcher());
Denis
fonte
Esta é, na verdade, uma maneira inteligente e leve de resolver o problema! obrigado!
FRR de
2

Para Kotlin, use a função de extensão KTX : (usa TextWatchercomo respostas 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
fonte
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
fonte
1

se você implementar com diálogo edittext. use assim :. é o mesmo com o uso para outro texto de edição.

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
fonte
-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 obter mais referências, clique aqui http://androiddhina.blogspot.in/2015/05/android-textwatcher.html

Dhina k
fonte