文字变更监听器上的android


265

我有一个情况,有两个领域。field1field2field2field1更改时,我只想做空,反之亦然。因此,最后只有一个字段具有内容。

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,依此类推...

有人可以提出任何解决方案吗?


对于新用户,请使用字符串的observable-field进行两种方式的数据绑定,导致此处提供的所有解决方案都可能产生starting waiting blocking gc alloc这种类型的错误,甚至可能导致崩溃和挂起。安全和建议现在的谷歌..
Maifee的UI阿萨德

Answers:


460

您可以添加一个检查以仅在字段中的文本不为空(即长度不为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 此处的文档。

另外,请遵守命名约定


1
如何在所有字段更改后进行检测,因为它会在每次更改时检测到何时按下任何按钮。
拉斐尔·吉马良斯19'Oct

20

我知道这已经很老了,但总有一天可能有人再次遇到这个问题。

我有一个类似的问题,我会在EditText上调用setText,而在我不希望它调用时会调用onTextChanged。我的第一个解决方案是在调用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();
   }
  });

11

如果您使用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) {}
    })

5

答案有点晚了,但这是一个可重用的解决方案:

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

因此,使用上面的方法时,setText()TextWatcher中发生的任何调用都不会导致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) {
    }
}

5

我也遇到了同样的问题,并不断遇到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;
        }
    }
});

最初声明为boolean skipOnChange = false;


1
“堆栈已满”,我认为您的意思是堆栈溢出;)
Droid

4

您还可以使用hasFocus()方法:

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

在大学课程中测试了此功能,我正在研究如何在用户键入温度标度时转换温度标度。完美地工作,并且更简单。


1
当用户输入editText.setText时呢?EditText在这种情况下具有焦点
Evgenii Vorobei

最好的解决方案。
Syed Hissaan'2

3

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

您可以检查String长度的另一种方法是:

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

2

我为此写了自己的扩展名,对我很有帮助。(科特琳)

您只能这样写:

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

2
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的新活动代码,我的应用程序基本上是note应用程序。

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) {

            }
        });
    }
}

1

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"

1

我们可以在编辑文本之前删除字段的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)域2

在更改field2文本之前,请删除TextWatcher: field2.removeTextChangedListener(Field_2_Watcher) 更改文本: field2.setText("")

然后重新添加TextWatcher: field2.addTextChangedListener(Field_2_Watcher)

在其他领域做同样的事情


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.