Android 实现多个EditText互相监听遇到的问题及解决方法

上周在实现一个功能的时候遇到了很多问题,然后折腾了好久才解决,以防今后又遇上同样的问题特在此记录下。

我实现的功能要求是一个界面上有四个EditText控件,其中任意一个内容变化,其他三个都要根据算法做出相应变化,这就牵扯到了多个EditText相互监听的问题了。

要实现EditText的监听就会用到TextWatcher;

首先我们来了解一下TextWatcher的用法吧!

功能:

1.监听EditText里输入内容的变化;

2.根据实时输入的文字内容,做出输入自动提示效果

TextWatcher myWatcher = newTextWatcher(){

@Override
public void onTextChanged(CharSequence s,int start,int before,int count){
     System.out.println("onTextChanged");
     System.out.println("s = "+s+",start = "+start+",before = "+before+",count = "+count);
}

@Override
public void beforeTextChanged(CharSequence s,int start,int count,int after){
     System.out.println("beforeTextChanged");
     System.out.println("s = "+s+",start = "+start+",count = "+count+",after = "+after);
}

@Override
public void afterTextChanged(Editable s){
     System.out.println("afterTextChanged");
     System.out.println("s = " + s);
}
};
大家可以根据各参数打印出来的结果了解参数具体指什么;

触发过程:

1.beforeTextChanged(CharSequence s,int start,int count,int after);

在EditText里的内容即将发生变化之前触发,EditText里的内容变化有3种方式:

1.新增加字符;2.删除字符;3.替换输入框中的若干个字符。

该方法反映的是,EditText在要发生变化之前,原来的内容字符串s有哪几个字符将要发生何种变化。

无论何种变化方式,都可以理解为:输入框的原内容字符串s,从索引位置start开始,

有count个字符即将被替换, 替换这count个字符的新的字符个数为after

注意:s是变化之前的输入框内容

2.onTextChanged(CharSequence s,int start,int before,int count);

在EditText里的内容发生变化之时触发,

在变化时的新的字符串s里,从索引位置start开始,有count个字符,是替换了原来的before个字符的

注意:s是变化之后的输入框内容

3.afterTextChanged(Editable s)

text变化之后触发,s是最终新的输入框内容


问题一:

接下来当我最初开始使用edittext的TextWatcher,运行程序时出现了java.lang.StackOverflowError错误,

经过分析知道,每次使用setText()方法为EditText添加数据时,会重新触发监听器,并不断的进行递归,造成死循环,最后程序崩溃。

针对这个,我试了两种解决方案:

1. 设置一个flag, 例:

private boolean autochange = false;

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
    if(autochange) { // skip execution if triggered by code
       autochange=false; // next change is not triggered by code
       return;
    }
    if (s.length() != 0) {
        switch (et.getId()) {
        case R.id.etUsername: {

        }
        break;

        case R.id.etPassword: {
            phone = formatPhoneNumber(phone);
            Log.i("PHONE", "Phone NUMB IS:"+phone);
            autochange=true;
            mPassword.setText(phone); 
        }
        }
    }
}   

2. 每次设置文本的时候移除原来的监听,然后再重置一个监听:

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
    //Toast.makeText(getApplicationContext(), "In onTextChanged() Method", Toast.LENGTH_SHORT).show();
    if (s.length() != 0) {
        switch (et.getId()) {
        case R.id.etUsername: {

        }
        break;

        case R.id.etPassword: {
            mPassword.removeTextChangedListener(theWatcher);
            phone = formatPhoneNumber(phone);
            Log.i("PHONE", "Phone NUMB IS:"+phone);
            mPassword.setText(phone);  //THE ERROR HAPPENS HERE
            mPassword.addTextChangedListener(theWatcher); 
        }
        }
    }
} 

问题二:

错误:android.content.res.Resources$NotFoundException

原因:一般发生在参数 int resId 错误,你把String赋值给int的resId,所以编译器找不到正确的resource于是报错。

检查一下edittext.setText之类的函数,这种函数通常有几个重载,如:

editText.setText(CharSequence text);

editText.setText(int resId);

......

如果不小心将一个int值传给了它,那它不会显示该int值,而是跑到工程下去找一个对应的resource的id,当然是找不到的,于是就报错啦。

解决办法是使用String.valueOf,例:

count.setText(String.valueOf(incall.getCount())); 

问题三:

多个EditText相互监听死循环:可以在每个EditText聚焦时再监听其文本变化,即先给edittext设置setOnTouchListener, 然后在此下面进行TextWatcher.


你可能感兴趣的:(死循环,TextWatcher)