java textvaluechanged 全选删除不触发_java - 如何在不触发Text Watcher的情况下更改EditText文本?...

java - 如何在不触发Text Watcher的情况下更改EditText文本?

我有一个EditText字段,上面有一个Customer Text Watcher。 在一段代码中,我需要使用TextWatcher更改EditText中的值。

问题是,一旦我进行了更改,就会调用TextWatcher方法创建一个无限循环。 如何在不触发afterTextChanged的情况下更改文本?

我需要在afterTextChanged方法中的文本,所以不建议删除TextWatcher。

12个解决方案

68 votes

您可以检查当前哪个View具有焦点,以区分用户和程序触发的事件。

EditText myEditText = (EditText) findViewById(R.id.myEditText);

myEditText.addTextChangedListener(new TextWatcher() {

@Override

public void onTextChanged(CharSequence s, int start, int before, int count) {

if (getCurrentFocus() == myEditText) {

// is only executed if the EditText was directly changed by the user

}

}

//...

});

编辑:正如LairdPleng正确提到的,如果myEditText已经具有焦点并且您以编程方式更改文本,则此方法无效。 因此,在致电myEditText.clearFocus()之前,你应该拨打myEditText.clearFocus(),因为Chack说,这也解决了这个问题。

Willi Mentzel answered 2019-06-15T06:15:42Z

49 votes

您可以取消注册观察者,然后重新注册它。

或者,您可以设置一个标志,以便您的观察者知道您何时自己更改了文本(因此应该忽略它)。

CasualT answered 2019-06-15T06:15:03Z

12 votes

很容易修复...只要你的逻辑推导出新的编辑文本值是幂等的(它可能会,但只是说)。 在侦听器方法中,如果当前值与上次修改值不同,则仅修改编辑文本。

例如。,

TextWatcher tw = new TextWatcher() {

private String lastValue = "";

@Override

public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

}

@Override

public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

}

@Override

public void afterTextChanged(Editable editable) {

// Return value of getNewValue() must only depend

// on the input and not previous state

String newValue = getNewValue(editText.getText().toString());

if (!newValue.equals(lastValue)) {

lastValue = newValue;

editText.setText(newValue);

}

}

};

Jeffrey Blattman answered 2019-06-15T06:16:26Z

11 votes

public class MyTextWatcher implements TextWatcher {

private EditText et;

// Pass the EditText instance to TextWatcher by constructor

public MyTextWatcher(EditText et) {

this.et = et;

}

@Override

public void afterTextChanged(Editable s) {

// Unregister self before update

et.removeTextChangedListener(this);

// The trick to update text smoothly.

s.replace(0, s.length(), "text");

// Re-register self after update

et.addTextChangedListener(this);

}

}

用法:

et_text.addTextChangedListener(new MyTextWatcher(et_text));

如果您使用editText.setText()而不是editable.replace(),则在快速输入文本时可能会感到有点滞后。

Chan Chun Him answered 2019-06-15T06:17:11Z

3 votes

嗨,如果您需要专注于EditText更改文本,您可以请求焦点。 这对我有用:

if (getCurrentFocus() == editText) {

editText.clearFocus();

editText.setText("...");

editText.requestFocus();

}

Milos Simic Simo answered 2019-06-15T06:17:41Z

1 votes

试试这个逻辑:我想setText(“”)而不去无限循环,这段代码适合我。 我希望你能修改它以满足你的要求

final EditText text= (EditText)findViewById(R.id.text);

text.addTextChangedListener(new 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) {

}

@Override

public void afterTextChanged(Editable s) {

if(s.toString().isEmpty())return;

text.setText("");

//your code

}

});

ShAkKiR answered 2019-06-15T06:18:15Z

0 votes

我的变种:

public class CustomEditText extends AppCompatEditText{

TextWatcher l;

public CustomEditText(Context context, AttributeSet attrs) {

super(context, attrs);

}

public void setOnTextChangeListener(TextWatcher l) {

try {

removeTextChangedListener(this.l);

} catch (Throwable e) {}

addTextChangedListener(l);

this.l = l;

}

public void setNewText(CharSequence s) {

final TextWatcher l = this.l;

setOnTextChangeListener(new 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) {

}

@Override

public void afterTextChanged(Editable s) {

}

});

setText(s);

post(new Runnable() {

@Override

public void run() {

setOnTextChangeListener(l);

}

});

}

}

仅使用setOnTextChangeListener()设置侦听器,并仅使用setNewText设置文本(我想覆盖setText(),但它是最终的)

danpetruk answered 2019-06-15T06:18:54Z

0 votes

从文本更改的侦听器中设置文本时,可能会发生无限循环。如果是这种情况,也许最好不要首先从那里设置文本。因此,您将解决循环问题,并且没有理由绕过或使用该事件。

auval answered 2019-06-15T06:19:26Z

0 votes

我创建了一个抽象类,它减轻了通过TextWatcher对EditText进行修改时的循环问题。

/**

* An extension of TextWatcher which stops further callbacks being called as a result of a change

* happening within the callbacks themselves.

*/

public abstract class EditableTextWatcher implements TextWatcher {

private boolean editing;

@Override

public final void beforeTextChanged(CharSequence s, int start, int count, int after) {

if (editing)

return;

editing = true;

try {

beforeTextChange(s, start, count, after);

} finally {

editing = false;

}

}

abstract void beforeTextChange(CharSequence s, int start, int count, int after);

@Override

public final void onTextChanged(CharSequence s, int start, int before, int count) {

if (editing)

return;

editing = true;

try {

onTextChange(s, start, before, count);

} finally {

editing = false;

}

}

abstract void onTextChange(CharSequence s, int start, int before, int count);

@Override

public final void afterTextChanged(Editable s) {

if (editing)

return;

editing = true;

try {

afterTextChange(s);

} finally {

editing = false;

}

}

public boolean isEditing() {

return editing;

}

abstract void afterTextChange(Editable s);

}

Eurig Jones answered 2019-06-15T06:19:57Z

0 votes

这是一个方便的类,它提供了一个比TextWatcher更简单的接口,用于希望在发生更改时查看更改的正常情况。 它还允许忽略OP请求的下一个更改。

public class EditTexts {

public final static class EditTextChangeListener implements TextWatcher {

private final Consumer onEditTextChanged;

private boolean ignoreNextChange = false;

public EditTextChangeListener(Consumer onEditTextChanged){

this.onEditTextChanged = onEditTextChanged;

}

public void ignoreNextChange(){

ignoreNextChange = true;

}

@Override public void beforeTextChanged(CharSequence __, int ___, int ____, int _____) { }

@Override public void onTextChanged(CharSequence __, int ___, int ____, int _____) { }

@Override public void afterTextChanged(Editable s) {

if (ignoreNextChange){

ignoreNextChange = false;

} else {

onEditTextChanged.accept(s.toString());

}

}

}

}

像这样用它:

EditTexts.EditTextChangeListener listener = new EditTexts.EditTextChangeListener(s -> doSomethingWithString(s));

editText.addTextChangedListener(listener);

每当您想要修改editText的内容而不导致级联的递归编辑时,请执行以下操作:

listener.ignoreNextChange();

editText.setText("whatever"); // this won't trigger the listener

JohnnyLambada answered 2019-06-15T06:20:44Z

0 votes

我用那种方式:

mEditText.addTextChangedListener(new 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) {}

@Override

public void afterTextChanged(Editable s) {

if (mEditText.isFocused()) { //

mEditText.setTag(true);

}

}

});

每当您需要以编程方式更改文本时,请先清除焦点

mEditText.clearFocus();

mEditText.setText(lastAddress.complement);

Arthur Melo answered 2019-06-15T06:21:26Z

-1 votes

您应该确保文本更改的实现是稳定的,并且如果不需要更改则不会更改文本。 通常情况下,这将是已经通过观察者一次的任何内容。

最常见的错误是在关联的EditText或Editable中设置新文本,即使文本实际上没有更改。

最重要的是,如果您对可编辑视图进行了更改而不是某些特定视图,您可以轻松地重新使用您的观察者,并且您可以单独使用某些单元测试来测试它,以确保它具有您想要的结果。

由于Editable是一个接口,你甚至可以使用它的虚拟实现,如果在测试应该稳定的内容时调用任何尝试更改其内容的方法,则会抛出RuntimeException。

thoutbeckers answered 2019-06-15T06:22:27Z

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值