Как использовать класс TextWatcher в Android?
Может кто-нибудь сказать мне, как замаскировать подстроку в EditText или как изменить ввод подстроки EditText на тип пароля или заменить другим символом, как этот 123xxxxxxxxx3455
String contents = et1.getText().toString();
et1.setText(contents.replace.substring(0, contents.length()-2),"*");
Пожалуйста, расскажите мне, как я могу использовать метод TextWatcher в Android.
12 ответов
Для использования 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
}
});
TextWatcher
Интерфейс имеет 3 метода обратного вызова, которые вызываются в следующем порядке, когда в тексте произошли изменения:
1 beforeTextChanged(CharSequence s, int start, int count, int after)
Вызывается до того, как изменения были применены к тексту.s
Параметр - это текст перед применением любого изменения.start
Параметр - это позиция начала измененной части в тексте.count
Параметр - длина измененной части в s
Последовательность с start
позиция.
И after
Параметр - это длина новой последовательности, которая заменит часть s
последовательность из start
в start+count
,
Вы не должны изменять текст в TextView
из этого метода (с помощью myTextView.setText(String newText)
).
2 onTextChanged(CharSequence s, int start, int before, int count)
Похож на beforeTextChanged
метод, но вызывается после изменения текста.s
Параметр - это текст после внесения изменений.start
Параметр такой же, как в beforeTextChanged
метод.count
параметр является after
параметр в методе beforeTextChanged.
И before
параметр является count
параметр в методе beforeTextChanged.
Вы не должны изменять текст в TextView
из этого метода (с помощью myTextView.setText(String newText)
).
3 afterTextChanged(Editable s)
Вы можете изменить текст в TextView
из этого метода.
/! \ Предупреждение: при изменении текста в TextView
, TextWatcher
будет запущен снова, начиная бесконечный цикл. Затем вы должны добавить как boolean _ignore
свойство, которое предотвращает бесконечный цикл.
Exemple:
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...
}
Резюме:
Мой пользовательский слушатель:
Лично я сделал свой собственный текстовый слушатель, который дает мне 4 части в отдельных строках, что для меня гораздо более интуитивно понятно.
/**
* 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;
}
}
Пример:
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();
}
Дополнительный ответ
Вот визуальное дополнение к другим ответам. Мой более полный ответ с кодом и пояснениями здесь.
- Красный: текст, который будет удален (заменен)
- Зеленый: текст, который был только что добавлен (заменив старый красный текст)
Для Kotlin используйте функцию расширения KTX:(Он используетTextWatcher
как предыдущие ответы)
yourEditText.doOnTextChanged { text, start, count, after ->
// action which will be invoked when the text is changing
}
Импортировать core-KTX
:
implementation "androidx.core:core-ktx:1.2.0"
Использование TextWatcher в Android
Вот пример кода. Попробуйте использовать addTextChangedListener
метод 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);
}
}
});
Немного большая перспектива решения:
@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;
}
Это работает для меня, делая это в первый раз.
Создать пользовательский подкласс 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);
}
}
Установите слушателя для вашего EditText:
mTargetEditText.addTextChangedListener(new CustomWatcher());
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) {
}
}
}
Если вы реализуете с помощью диалога edittext. использовать так: то же самое с использованием другого текста редактирования.
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) {
}
});
Я не хочу переопределять/реализовывать все методыTextWatcher
и положиstub
код в методах, которые я не использую, поэтому для простоты :-) Я создал абстрактный классTextObserver
и вуаля проблема решена.
Не знаю, почему они все равно реализовали его как интерфейс, а не как абстрактный класс, потому что большую часть времени используется только один метод, а интерфейс — это контракт, в котором говорится, что все методы должны быть реализованы.
package com.mindef.idttpda.shared;
// dependencies
import android.text.Editable;
import android.text.TextWatcher;
/**
* text watcher is converted to abstract class because
* then not all methods have to be overridden.
*/
public abstract class TextObserver implements TextWatcher {
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
public void afterTextChanged(Editable editable) {}
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
}
Я не хочу реализовывать все методыTextWatcher
чтобы я создал абстрактный классTextObserver
и вуаля проблема решена:
package com.mindef.idttpda.shared;
// dependencies
import android.text.Editable;
import android.text.TextWatcher;
/**
* text watcher is converted to abstract class because
* then not all methods have to be overridden.
*/
public abstract class TextObserver implements TextWatcher {
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
public void afterTextChanged(Editable editable) {}
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
}
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()));
}
});
Для получения дополнительной информации нажмите здесь http://androiddhina.blogspot.in/2015/05/android-textwatcher.html