Jak korzystać z klasy TextWatcher w systemie Android?

104

Czy ktoś może mi powiedzieć, jak zamaskować podciąg w EditTextlub jak zmienić EditText dane wejściowe podciąg na typ hasła lub zastąpić innym znakiem, takim jak ten 123xxxxxxxxx3455

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

Proszę, powiedz mi, jak mogę użyć tej TextWatchermetody w systemie Android.

Programista Androida
źródło

Odpowiedzi:

174

Do korzystania z 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
źródło
59
co zrobić z tym TextWatcherem? Podaj więcej szczegółów, aby lepiej zrozumieć.
Paresh Mayani
W metodzie, która jest nadpisywana dla obserwatora tekstu. możesz zamaskować tekst, który naprawdę chciałeś.
Dinesh Prajapati
2
ale nie wiem, jak korzystać z TextWatchera, czy możesz wyjaśnić małym przykładem dzięki za wytyczne
programista Androida
umieść ten kod w java ... jak tylko użytkownik wpisze tekst, jedna z metod zostanie wywołana ... zgodnie z nazwą funkcji.
Dinesh Prajapati,
1
Właściwie, jeśli jest to wymóg, lepiej nie używać obserwatora tekstu. Będzie to nieskończona pętla
Dinesh Prajapati,
120

TextWatcherInterfejs ma 3 sposoby wywołania zwrotne które nazywane są w następującej kolejności, gdy nastąpiła zmiana w tekście:

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

Wywoływane przed zastosowaniem zmian w tekście. Parametr jest tekst przed stosowana jest jakakolwiek zmiana. Parametrem jest pozycja od początku zmienionych części w tekście. Parametrem jest długość zmienionych części w kolejności od tej pozycji. A parametrem jest długość nowej sekwencji, która zastąpi część sekwencji od do . Nie możesz zmieniać tekstu w z tej metody (używając ).
s
start
countsstart
aftersstartstart+count
TextViewmyTextView.setText(String newText)

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

Podobna do beforeTextChangedmetody, ale wywoływana po zmianie tekstu. Parametr jest tekst po zmiany zostały zastosowane. Parametr są takie same jak w metodzie. Parametrem jest parametrem sposobu beforeTextChanged. A parametrem jest parametr w metodzie beforeTextChanged. Nie możesz zmieniać tekstu w z tej metody (używając ).
s
startbeforeTextChanged
countafter
beforecount
TextViewmyTextView.setText(String newText)

afterTextChanged(Editable s)

Możesz zmienić tekst w TextViewz tej metody.
/! \ Ostrzeżenie: Kiedy zmienisz tekst w TextView, TextWatchernastąpi ponowne wyzwolenie, rozpoczynając nieskończoną pętlę. Następnie należy dodać boolean _ignorewłaściwość, która zapobiega nieskończonej pętli.
Przykład:

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

Podsumowanie:

wprowadź opis obrazu tutaj


Klasa gotowa do użycia: TextViewListener

Osobiście stworzyłem własny odbiornik tekstu, który daje mi 4 części w oddzielnych ciągach, co jest dla mnie znacznie bardziej intuicyjne w użyciu.

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

Przykład:

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
źródło
Problem z tym kodem polega na tym, że kursor nie pozostaje, gdyby miał być, a przynajmniej takie było moje doświadczenie.
jonasxd360
Czy to textview wywołuje te metody
Tak przypuszczam
Yairopro
naprawiony problem z kursorem w ten sposób: chronione void onTextChanged (ciąg przed, ciąg stary, ciąg aNew, ciąg po, sekwencja do edycji)
Eugene Strelnikov
50

Dodatkowa odpowiedź

Oto wizualne uzupełnienie innych odpowiedzi. Moja pełniejsza odpowiedź z kodem i objaśnieniami jest tutaj .

  • Czerwony: tekst, który ma zostać usunięty (zastąpiony)
  • Zielony: tekst, który właśnie został dodany (zastępujący stary czerwony tekst)

wprowadź opis obrazu tutaj

Suragch
źródło
6

Korzystanie z TextWatchera w systemie Android

Oto przykładowy kod. Spróbuj użyć addTextChangedListenermetody 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
źródło
5

Trochę większa perspektywa rozwiązania:

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

To działa dla mnie, robię to za pierwszym razem.

Berit Larsen
źródło
5

Utwórz niestandardową podklasę 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);

    }
}

Ustaw odbiornik dla EditText:

mTargetEditText.addTextChangedListener(new CustomWatcher());
Denis
źródło
W rzeczywistości jest to sprytny, lekki sposób rozwiązania problemu! dzięki!
FRR
3

Dla Kotlin użyj funkcji rozszerzenia KTX : (używa TextWatcherjak poprzednie odpowiedzi)

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


import core-KTX:

implementation "androidx.core:core-ktx:1.2.0"
Francis
źródło
to działa dla mnie
adrian4aes
2
    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
źródło
2

jeśli implementujesz z dialogiem edittext. użyj w ten sposób :. to samo z użyciem do innych edytorów.

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
źródło
-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()));
      }

         });

Aby uzyskać więcej informacji, kliknij tutaj http://androiddhina.blogspot.in/2015/05/android-textwatcher.html

Dhina K.
źródło