android的文本更改监听器

我有一个情况,其中有两个字段。field1field2。我想要的 当field1被改变时,做的是空field2,反之亦然。所以只有在最后

field1 = (EditText)findViewById(R.id.field1);
field2 = (EditText)findViewById(R.id.field2);


field1.addTextChangedListener(new TextWatcher() {


public void afterTextChanged(Editable s) {}


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


public void onTextChanged(CharSequence s, int start,
int before, int count) {
field2.setText("");
}
});


field2.addTextChangedListener(new TextWatcher() {


public void afterTextChanged(Editable s) {}


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


public void onTextChanged(CharSequence s, int start,
int before, int count) {
field1.setText("");
}
});
如果我只将addTextChangedListener附加到field1,则工作正常,但当 我对两个字段都这么做,应用程序崩溃了。显然是因为他们想要改变 无限地相互联系。一旦field1改变,它就会在此时清除field2 field2被更改,因此它将清除field1等等

谁能给点建议吗?

534579 次浏览

您可以添加一个检查,只在字段中的文本不为空时清除(即当长度不等于0时)。

field1.addTextChangedListener(new TextWatcher() {


@Override
public void afterTextChanged(Editable s) {}


@Override
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}


@Override
public void onTextChanged(CharSequence s, int start,
int before, int count) {
if(s.length() != 0)
field2.setText("");
}
});


field2.addTextChangedListener(new TextWatcher() {


@Override
public void afterTextChanged(Editable s) {}


@Override
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}


@Override
public void onTextChanged(CharSequence s, int start,
int before, int count) {
if(s.length() != 0)
field1.setText("");
}
});

TextWatcher 在这里文档。

也请尊重命名约定

在将另一个EditText设置为空之前检查字符串。如果Field1为空,那么为什么需要再次更改为("")?所以你可以用s.lenght ()或任何其他解决方案检查你的字符串的大小

另一种检查字符串长度的方法是:

String sUsername = Field1.getText().toString();
if (!sUsername.matches(""))
{
// do your job
}

我也遇到过同样的问题,并不断得到stackOverflow异常,我提出了以下解决方案。

edt_amnt_sent.addTextChangedListener(new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
if (skipOnChange)
return;


skipOnChange = true;
try {
//method
} catch (NumberFormatException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
skipOnChange = false;
}
}
});


edt_amnt_receive.addTextChangedListener(new TextWatcher() {


@Override
public void afterTextChanged(Editable s) {


if (skipOnChange)
return;


skipOnChange = true;
try {
//method
} catch (NumberFormatException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
skipOnChange = false;
}
}
});

skipOnChange = false;

你也可以使用hasFocus()方法:

public void onTextChanged(CharSequence s, int start,
int before, int count) {
if (Field2.hasfocus()){
Field1.setText("");
}
}

我在大学作业中测试了这个方法,在用户输入温标时转换温标。效果很好,而且简单多了。

我知道这很旧了,但某天有人可能会再次看到它。

我有一个类似的问题,我会在EditText和onTextChanged上调用setText,当我不希望它被调用时。我的第一个解决方案是在调用setText()之后编写一些代码来撤销侦听器所造成的损害。但这不是很优雅。 在做了一些研究和测试后,我发现使用getText().clear()以与setText("")相同的方式清除文本,但由于它没有设置文本,侦听器不会被调用,因此解决了我的问题。我把我所有的setText("")调用都切换到getText().clear(),我不再需要绷带了,所以也许这也会解决你的问题

试试这个:

Field1 = (EditText)findViewById(R.id.field1);
Field2 = (EditText)findViewById(R.id.field2);


Field1.addTextChangedListener(new TextWatcher() {


public void afterTextChanged(Editable s) {}


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


public void onTextChanged(CharSequence s, int start,
int before, int count) {
Field2.getText().clear();
}
});


Field2.addTextChangedListener(new TextWatcher() {


public void afterTextChanged(Editable s) {}


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


public void onTextChanged(CharSequence s, int start,
int before, int count) {
Field1.getText().clear();
}
});

这个回答有点晚了,但这里有一个可重复使用的解决方案:

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


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


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


protected abstract void afterTextChange(Editable s);
}

因此,当使用上述方法时,在TextWatcher中发生的任何setText()调用都不会导致TextWatcher再次被调用:

/**
* A setText() call in any of the callbacks below will not result in TextWatcher being
* called again.
*/
public class MyTextWatcher extends EditableTextWatcher {


@Override
protected void beforeTextChange(CharSequence s, int start, int count, int after) {
}


@Override
protected void onTextChange(CharSequence s, int start, int before, int count) {
}


@Override
protected void afterTextChange(Editable s) {
}
}

如果你正在使用Kotlin进行Android开发,那么你可以使用下面的代码添加TextChangedListener():

myTextField.addTextChangedListener(object : TextWatcher{
override fun afterTextChanged(s: Editable?) {}


override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}


override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
})

我写了自己的扩展,对我很有帮助。(芬兰湾的科特林)

你可以这样写:

editText.customAfterTextChanged { editable ->
//You have accessed the editable object.
}

我的分机号:

fun EditText.customAfterTextChanged(action: (Editable?)-> Unit){
this.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
override fun afterTextChanged(editable: Editable?) {
action(editable)
}
})}

onCreate方法中动态添加后台:

getWindow().setBackgroundDrawableResource(R.drawable.background);

也从XML中删除背景。

editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {


}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
if (noteid != -1) {
MainActivity.notes.set(noteid, String.valueOf(charSequence));
MainActivity.arrayAdapter.notifyDataSetChanged();
}
}
@Override
public void afterTextChanged(Editable editable) {


}
});

在这段代码中,noteid基本上是被收回的参数,它被放入缩进中或通过缩进传递。

  Intent intent = getIntent();
noteid = intent.getIntExtra("noteid", -1);

下面的代码基本上是额外的代码,如果你想更清楚地理解的话。

how to make the menu or insert the menu in our code ,
create the  menu folder this the folder created by going into the raw
->rightclick->
directory->name the folder as you wish->
then click on the directory formed->
then click on new file and then name for file as you wish ie the folder name file
and now type the 2 lines code in it and see the magic.

新的活动代码命名为NoteEditor.java用于编辑目的,我的应用程序基本上是笔记应用程序。

package com.example.elavi.notes;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;
import android.widget.Toast;


import static android.media.CamcorderProfile.get;
public class NoteEditorActivity extends AppCompatActivity {
EditText editText;
int noteid;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_note_editor);
editText = findViewById(R.id.editText);
Intent intent = getIntent();
noteid = intent.getIntExtra("noteid", -1);
if (noteid != -1) {
String text = MainActivity.notes.get(noteid);
editText.setText(text);


Toast.makeText(getApplicationContext(),"The arraylist content is"+MainActivity.notes.get(noteid),Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(getApplicationContext(),"Here we go",Toast.LENGTH_SHORT).show();
MainActivity.notes.add("");
noteid=MainActivity.notes.size()-1;
}
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {


}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
if (noteid != -1) {
MainActivity.notes.set(noteid, String.valueOf(charSequence));
MainActivity.arrayAdapter.notifyDataSetChanged();
}
}
@Override
public void afterTextChanged(Editable editable) {


}
});
}
}
芬兰湾的科特林中简单地使用KTX扩展函数: (它使用TextWatcher)

yourEditText.doOnTextChanged { text, start, count, after ->
// action which will be invoked when the text is changing
}
< p > < br > 进口core-KTX: < / p >
implementation "androidx.core:core-ktx:1.2.0"

我们可以在编辑文本之前删除字段的TextWatcher,然后在编辑文本之后将其添加回来。

field1field2的文本监视器声明为单独的变量,并为它们命名:例如,field1

private TextWatcher Field_1_Watcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}


@Override
public void afterTextChanged(Editable s) {
}


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


}


};

然后使用它的名称添加监视器: field1.addTextChangedListener(Field_1_Watcher)field1,和 field2.addTextChangedListener(Field_2_Watcher) for field2

在修改field2文本之前,删除TextWatcher: field2.removeTextChangedListener(Field_2_Watcher) 修改文本: field2.setText("") < / p >

然后添加回TextWatcher: field2.addTextChangedListener(Field_2_Watcher) < / p >

对另一个字段做同样的处理

另一个可能会帮助别人的解决方案。有2个EditText,它们在编辑后相互改变。默认情况下,它导致了周期性。

使用变量:

Boolean uahEdited = false;
Boolean usdEdited = false;

添加TextWatcher

uahEdit = findViewById(R.id.uahEdit);
usdEdit = findViewById(R.id.usdEdit);


uahEdit.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
if (!usdEdited) {
uahEdited = true;
}
}


@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
String tmp = uahEdit.getText().toString();


if(!tmp.isEmpty() && uahEdited) {
uah = Double.valueOf(tmp);
usd = uah / 27;
usdEdit.setText(String.valueOf(usd));
} else if (tmp.isEmpty()) {
usdEdit.getText().clear();
}
}


@Override
public void afterTextChanged(Editable s) {
uahEdited = false;
}
});


usdEdit.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
if (!uahEdited) {
usdEdited = true;
}
}


@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
String tmp = usdEdit.getText().toString();


if (!tmp.isEmpty() && usdEdited) {
usd = Double.valueOf(tmp);
uah = usd * 27;
uahEdit.setText(String.valueOf(uah));
} else if (tmp.isEmpty()) {
uahEdit.getText().clear();
}
}


@Override
public void afterTextChanged(Editable s) {
usdEdited = false;
}
});

不要批评太多。我是一个开发新手

var filenameText = findViewById(R.id.filename) as EditText
filenameText.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
filename = filenameText.text.toString()
Log.i("FileName: ", filename)
}
    

override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
})
etSearch.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
TODO("Not yet implemented")
}


override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
TODO("Not yet implemented")
}


override fun afterTextChanged(p0: Editable?) {
TODO("Not yet implemented")
}
})