很多App中都有话题这个功能,类似于微博的话题,以#我是话题#这种形式展现。话题的颜色区分于普通文本的颜色。一般的思路是用正则表达式查找字符串中两个#中间的文字,如果查找到就当作话题,使用Spanable的setSpan方法设置颜色高亮。
代码例子:
MyTextWatcher textWatcher;
EditText mEtContent = (EditText) findViewById(R.id.et_content);
textWatcher = new MyTextWatcher();
mEtContent.addTextChangedListener(textWatcher);
private class MyTextWatcher implements 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){
mEtContent.removeTextChangedListener(textWatcher);
TopicUtils.textviewSpan(context, mEtContent, s.toString());
mEtContent.addTextChangedListener(textWatcher);
}
}
TopicUtils.textviewSpan();这个方法就是为话题改变颜色和添加点击事件。
官网上讲It is legitimate to make further changes to s
from this callback, but be careful not to get yourself into an infinite loop, because any changes you make will cause this method to be called again recursively.意思是在afterTextChanged里面对s进行进一步的改变是合法的,但是要小心进入死循环,因为对s的改动会使afterTextChanged方法再次被回调。
所以在TopicUtils.textviewSpan()执行之前removeTextChangedListener ,在执行之后重新addTextChangedListener()。
ok,当我以为万事大吉的时候,有bug来了。原因是部分手机在使用系统的中文输入法时,使用拼音全键这种方式时,每次点击英文字母但是没有选择词语推荐(candidates)的时候都会触发afterTextChanged这个方法。解决办法如下:
private boolean canEdit = true;
private class MyTextWatcher implements 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){
if (canEdit) {
canEdit = false;
mEtContent.removeTextChangedListener(textWatcher);
TopicUtils.textviewSpan(context, mEtContent, s.toString());
mEtContent.addTextChangedListener(textWatcher);
}
}
}