Answers:
我刚遇到这个问题。我通过创建一个内部类实现来解决它,该实现TextWatcher
将View作为参数。然后,在该方法实施方式中,只是打开视图以查看哪一个Editable
是来自
宣言:
private class GenericTextWatcher implements TextWatcher{
private View view;
private GenericTextWatcher(View view) {
this.view = view;
}
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
public void afterTextChanged(Editable editable) {
String text = editable.toString();
switch(view.getId()){
case R.id.name:
model.setName(text);
break;
case R.id.email:
model.setEmail(text);
break;
case R.id.phone:
model.setPhone(text);
break;
}
}
}
用法:
name = (EditText) findViewById(R.id.name);
name.setText(model.getName());
name.addTextChangedListener(new GenericTextWatcher(name));
email = (EditText) findViewById(R.id.email);
email.setText(model.getEmail());
email.addTextChangedListener(new GenericTextWatcher(email));
phone = (EditText) findViewById(R.id.phone);
phone.setText(model.getPhone());
phone.addTextChangedListener(new GenericTextWatcher(phone));
Single TextWatcher for multiple EditTexts
。它是一个TextWatcher类的3个实例。因此,有3个单独的TextWatcher控制着3个EditText。
如果只想使用afterTextChanged比较可编辑内容:
@Override
public void afterTextChanged(Editable editable) {
if (editable == mEditText1.getEditableText()) {
// DO STH
} else if (editable == mEditText2.getEditableText()) {
// DO STH
}
}
==
而不是时,此选项才能正常工作.equals()
。
public class MultiTextWatcher {
private TextWatcherWithInstance callback;
public MultiTextWatcher setCallback(TextWatcherWithInstance callback) {
this.callback = callback;
return this;
}
public MultiTextWatcher registerEditText(final EditText editText) {
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
callback.beforeTextChanged(editText, s, start, count, after);
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
callback.onTextChanged(editText, s, start, before, count);
}
@Override
public void afterTextChanged(Editable editable) {
callback.afterTextChanged(editText, editable);
}
});
return this;
}
interface TextWatcherWithInstance {
void beforeTextChanged(EditText editText, CharSequence s, int start, int count, int after);
void onTextChanged(EditText editText, CharSequence s, int start, int before, int count);
void afterTextChanged(EditText editText, Editable editable);
}
}
new MultiTextWatcher()
.registerEditText(editText1)
.registerEditText(editText2)
.registerEditText(editText3)
.setCallback(new TextWatcherWithInstance() {
@Override
public void beforeTextChanged(EditText editText, CharSequence s, int start, int count, int after) {
// TODO: Do some thing with editText
}
@Override
public void onTextChanged(EditText editText, CharSequence s, int start, int before, int count) {
// TODO: Do some thing with editText
}
@Override
public void afterTextChanged(EditText editText, Editable editable) {
// TODO: Do some thing with editText
}
});
TextView
更改来自何处。
如果要使用下面提到的onTextChanged比较hashCode()
-
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
if(charSequence.hashCode() == first_edit_text.getText().hashCode()){
// do other things
}
if(charSequence.hashCode() == second_edit_text.getText().hashCode()){
// do other things
}
}
要么
如果要使用afterTextChanged比较Editable
下面提到的-
@Override
public void afterTextChanged(Editable editable) {
if (editable == first_edit_text.getEditableText()) {
// do other things
} else if (editable == second_edit_text.getEditableText()) {
// do other things
}
}
它将与此代码一起工作
TextWatcher watcher = new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
//YOUR CODE
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
//YOUR CODE
}
@Override
public void afterTextChanged(Editable s) {
String outputedText = s.toString();
mOutputText.setText(outputedText);
}
};
然后在oncreate中添加它
mInputText.addTextChangedListener(watcher);
e2.addTextChangedListener(watcher);
e3.addTextChangedListener(watcher);
e4.addTextChangedListener(watcher);
我知道这是一个老问题,有正确的决定。我会自己写,也许会帮助别人。
模拟经典示例,其中有N个EditText,并且如果所有字段都已填充,我们想显示按钮。这个例子很有意义,特别是如果每个验证器都使用验证器的话。
我就这个问题举了一个例子,但是你可以做任何设置
MultiEditText.class
public class MultiEditText extends AppCompatActivity{
EditText ed_1, ed_2, ed_3;
Button btn_ok;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.multi_edit_text);
ed_1 = (EditText) findViewById(R.id.ed_1);
ed_2 = (EditText) findViewById(R.id.ed_2);
ed_3 = (EditText) findViewById(R.id.ed_3);
btn_ok = (Button) findViewById(R.id.btn_ok);
btn_ok.setEnabled(false);
//if want more here can cycle interface List
EditText[] edList = {ed_1, ed_2, ed_3};
CustomTextWatcher textWatcher = new CustomTextWatcher(edList, btn_ok);
for (EditText editText : edList) editText.addTextChangedListener(textWatcher);
}
}
现在看起来很简单
public class CustomTextWatcher implements TextWatcher {
View v;
EditText[] edList;
public CustomTextWatcher(EditText[] edList, Button v) {
this.v = v;
this.edList = edList;
}
@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) {
for (EditText editText : edList) {
if (editText.getText().toString().trim().length() <= 0) {
v.setEnabled(false);
break;
}
else v.setEnabled(true);
}
}
}
我将添加一个布局,这样您就不会浪费时间
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<EditText
android:id="@+id/ed_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="8dp" />
<EditText
android:id="@+id/ed_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/ed_1"
android:layout_centerHorizontal="true"
android:layout_marginTop="8dp" />
<EditText
android:id="@+id/ed_3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/ed_2"
android:layout_centerHorizontal="true"
android:layout_marginTop="8dp" />
<Button
android:id="@+id/btn_ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/ed_3"
android:layout_centerHorizontal="true"
android:layout_marginTop="8dp"
android:text="OK" />
</RelativeLayout>
让您的类继承自Activity并实现TextWatcher。
然后,通过多态魔术,您只需要订阅事件即可。
这不会告诉您TextEdit发生了什么变化,但是结合使用此选项和Sky Kelsey的答案,您可以很好地进行分类。
public YourActivity extends Activity implements TextWatcher {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_YourActivity);
//Subscribe to the events
EditText txt1 = (EditText) findViewById(R.id.txt1);
txt1.addTextChangedListener(this);
EditText txt2 = (EditText) findViewById(R.id.txt2);
txt2.addTextChangedListener(this);
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
EditText txt1 = (EditText) findViewById(R.id.txt1);
EditText txt2 = (EditText) findViewById(R.id.txt2);
// You probably only want the text value from the EditText. But you get the idea.
doStuff(txt1,txt2);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.calc, menu);
return true;
}
@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// TODO Auto-generated method stub
}
}
TextWatcher watcher = 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) {
}
@Override
public void afterTextChanged(Editable editable) {
}
};
然后:
editText1.addTextChangedListener(watcher);
editText2.addTextChangedListener(watcher);
editText3.addTextChangedListener(watcher);
public class MainActivity extends AppCompatActivity{
EditText value1, value2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//instantiate EditText controls
value1 = (EditText)findViewById(R.id.txtValue1);
value2 = (EditText)findViewById(R.id.txtValue2);
//set up text changed listener
value1.addTextChangedListener(new TextChange(value1));
value2.addTextChangedListener(new TextChange(value2));
//inner class
private class TextChange implements TextWatcher {
View view;
private TextChange (View v) {
view = v;
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
switch (view.getId()) {
case R.id.txtValue1:
//insert your TextChangedListener codes here
break;
case R.id.txtValue2:
//insert your TextChangedListener codes here
break;
}
}
}
}
}
这是我对Kotlin的解决方案。您只需使用引用相等(===)来检查同一对象,即可正常工作。
val mTextWatcher = object : TextWatcher {
override fun afterTextChanged(et: Editable?) {
when {
et === et1.editableText -> {
Toast.makeText(this@MainActivity, "EditText 1", Toast.LENGTH_LONG).show()
}
et === et2.editableText -> {
Toast.makeText(this@MainActivity, "EditText 2", Toast.LENGTH_LONG).show()
}
}
}
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
}
et1.addTextChangedListener(mTextWatcher)
et2.addTextChangedListener(mTextWatcher)
我知道这个问题很旧,但是我想分享我的一种解决方案(在Kotlin中)。我的解决方案是@Shwarz Andrei的答案的改进,我的原因是如果您想操纵更多的事物/对象,该怎么办。
除了传递参数list of EditTexts
和a Button
作为参数之外,您只需传递即可list of editText
。然后,在您的自定义类中,您将实现一个lambda,例如:
var hasFilled:((Boolean)->Unit)? = null
然后,您可以在 afterTextChanged
override fun afterTextChanged(p0: Editable?) {
for (edit in _editTextList) {
if (edit?.text.toString().trim().isEmpty()) {
hasFilled?.invoke(false) //<-- here
break
} else {
hasFilled?.invoke(true) //<--- here
}
}
}
因此,每次您的lambda调用时,某些EditText都会发生变化
val editTexts = listOf(emailEditText,passwordEditText) // your list of editText
val textWatcher = customTextWatcher(editTexts) // initialize your custom object
editTexts.forEach { it -> it?.addTextChangedListener(textWatcher) } // each editText would listen for changes
textWatcher.hasFilled = { value -> // now you have access to your lambda
if (value != true) {
// change the state of the button to unable
// do other things
} else {
// change the state of the button to enable
// do other things
}
}
这是我的做法:
创建一个EditTexts的ArrayList,然后使用for循环将TextWatcher应用于所有EditTexts,如果您对所有editTexts具有一种行为,则将其应用于此处,如果对某些特定editTexts具有特定行为,则可以使用if选择并应用于单个editText的语句。
这是我的代码:
ArrayList<EditText> editTexts = new ArrayList<>(); // Container list
editText1 = (EditText) findViewById(R.id.editText1);
editText2 = (EditText) findViewById(R.id.editText2);
editText3 = (EditText) findViewById(R.id.editText3);
editTexts.add(editText1); // editTexts[0]
editTexts.add(editText2); // editTexts[1]
editTexts.add(editText3); // editTexts[2]
for (final EditText editText : editTexts) { //need to be final for custom behaviors
editText.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) {
//Apply general behavior for all editTexts
if (editText == editTexts.get(1)) {
//Apply custom behavior just for this editText
}
}
});
}
希望这可以帮助
onTextChanged
,与EditText 一样常见的东西似乎有点复杂。onFocusChange
为多个窗口小部件添加一个更加简单,因为它通过方法调用传递了sender对象。然后,您可以检查哪个对象触发了调用并从那里处理它。