Android 实现多个EditText互相监听遇到的问题及解决方法
2016-02-21 10:20
726 查看
上周在实现一个功能的时候遇到了很多问题,然后折腾了好久才解决,以防今后又遇上同样的问题特在此记录下。
我实现的功能要求是一个界面上有四个EditText控件,其中任意一个内容变化,其他三个都要根据算法做出相应变化,这就牵扯到了多个EditText相互监听的问题了。
要实现EditText的监听就会用到TextWatcher;
首先我们来了解一下TextWatcher的用法吧!
功能:
1.监听EditText里输入内容的变化;
2.根据实时输入的文字内容,做出输入自动提示效果
大家可以根据各参数打印出来的结果了解参数具体指什么;
触发过程:
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, 例:
2. 每次设置文本的时候移除原来的监听,然后再重置一个监听:
问题二:
错误: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.
我实现的功能要求是一个界面上有四个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.
相关文章推荐
- asp经常被忽视的一种死循环
- 基于Java HashMap的死循环的启示详解
- Java中一个for语句导致无穷大死循环的例子
- 记一次递归调用问题
- 无限循环陷阱
- TextWatcher参数理解
- IOS 懒加载,死循环
- 输入框字数限制+动态提示:10个汉字或20个字符的问题
- android项目中edittext的一些总结
- 找出java代码中占用cpu过多问题
- 死循环测试
- 死循环, break与return
- Android - TextWatcher监听事件的使用
- Android ListView 搜索关键字高亮显示
- 关闭窗体后,进程仍然在运行的问题重现与解决
- SpringMVC、Hibernate系列之级联对象的json序列化
- TextWatcher的使用
- 监控EditText中的输入内容并限制其输入字符个数
- c++循环变量溢出造成死循环
- AdapterView及Adapter分析