如何在 Android 中使用 TextWatcher 类?

有人能告诉我如何掩盖 EditText中的 子串或如何改变 EditText 密码类型的子字符串输入更换的另一个 性格喜欢这123xxxxxxx3455

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

请告诉我如何在 Android 中使用 TextWatcher方法。

207373 次浏览

For use of the 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
}
});

从更大的角度看待解决方案:

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

这对我很有用,我第一次这么做。

在 Android 中使用 TextWatcher

下面是一个示例代码。请尝试使用 TextView 的 addTextChangedListener方法

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

创建自定义 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) {
}
}
}

TextWatcher接口有3个回调方法,当文本发生更改时,这些方法都按以下顺序调用:

beforeTextChanged(CharSequence s, int start, int count, int after)
  • 称为 之前的更改已经应用于文本。
    s参数是 之前的短信,应用任何更改。
    start参数是文本中更改部分开头的 位置
    count参数是 s序列中从 start位置开始改变的部分的 length
    And the after parameter is the 新序列的长度 which will replace the part of the s sequence from start to start+count.
    从这个方法(通过使用 myTextView.setText(String newText))获得 TextView中的文本 不能改变
onTextChanged(CharSequence s, int start, int before, int count)`
  • 类似于 beforeTextChanged方法,但称为 之后的文本更改。
    s参数是已应用的 the text after更改。
    start参数与 beforeTextChanged方法中的参数相同。
    count参数是 before TextChanged 方法中的 after参数。
    before参数是 before TextChanged 方法中的 count参数。
    从这个方法(通过使用 myTextView.setText(String newText))获得 TextView中的文本 不能改变
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...
}

摘要:

enter image description here


一个可以使用的类: TextViewListener

就我个人而言,我做了我的自定义文本侦听器,它给我的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 use of parameters
String completeOldText = before + old + after;
String completeNewText = before + aNew + after;
           

// update TextView
startUpdates(); // to prevent infinite loop.
myEditText.setText(myNewText);
endUpdates();
}
}

补充答案

Here is a visual supplement to the other answers. My fuller answer with the code and explanations is 给你.

  • 红色: 文本即将被删除(替换)
  • 绿色: 刚刚添加的文本(替换旧的红色文本)

enter image description here

对于 科特林,使用 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"

如果你使用对话框编辑文本来实现。像这样使用: 。它和其他编辑文本的使用是一样的。

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的所有方法,我创建了一个抽象的类 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的所有方法,并把 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) {}
}