监听多个TextView的内容变化

使用示例
TextWatcherUtils.addTextChangedListener(isAllNotEmpty -> btnLogin.setEnabled(isAllNotEmpty), etCode, etPhone);
x
 
1
TextWatcherUtils.addTextChangedListener(isAllNotEmpty -> btnLogin.setEnabled(isAllNotEmpty), etCode, etPhone);
/**
* Desc:用于监听多个TextView的内容变化,常用于判断在登录注册时同时判断多个EditText是否都有输入内容,以判断是否允许点击下一步
*
* @author 白乾涛 <p>
* @tag 内容变化<p>
* @date 2018/5/22 22:01 <p>
*/
public class TextWatcherUtils { public interface OnTextChangedListener {
void onTextChanged(boolean isAllNotEmpty);
} public static void addTextChangedListener(OnTextChangedListener listener, TextView... tvs) {
for (TextView textView : tvs) {
textView.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) {
if (listener != null) {
listener.onTextChanged(isAllTextViewNotEmpty(tvs));
}
}
});
}
} private static boolean isAllTextViewNotEmpty(TextView[] tvs) {
for (TextView tv : tvs) {
if (TextUtils.isEmpty(tv.getText())) {
return false;
}
}
return true;
}
}
45
 
1
/**
2
 * Desc:用于监听多个TextView的内容变化,常用于判断在登录注册时同时判断多个EditText是否都有输入内容,以判断是否允许点击下一步
3
 *
4
 * @author 白乾涛 <p>
5
 * @tag 内容变化<p>
6
 * @date 2018/5/22 22:01 <p>
7
 */
8
public class TextWatcherUtils {
9
    
10
    public interface OnTextChangedListener {
11
        void onTextChanged(boolean isAllNotEmpty);
12
    }
13
    
14
    public static void addTextChangedListener(OnTextChangedListener listener, TextView... tvs) {
15
        for (TextView textView : tvs) {
16
            textView.addTextChangedListener(new TextWatcher() {
17
                @Override
18
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {
19
                
20
                }
21
                
22
                @Override
23
                public void onTextChanged(CharSequence s, int start, int before, int count) {
24
                
25
                }
26
                
27
                @Override
28
                public void afterTextChanged(Editable s) {
29
                    if (listener != null) {
30
                        listener.onTextChanged(isAllTextViewNotEmpty(tvs));
31
                    }
32
                }
33
            });
34
        }
35
    }
36
    
37
    private static boolean isAllTextViewNotEmpty(TextView[] tvs) {
38
        for (TextView tv : tvs) {
39
            if (TextUtils.isEmpty(tv.getText())) {
40
                return false;
41
            }
42
        }
43
        return true;
44
    }
45
}

仿QQ、微信、钉钉的@功能 案例

功能
1、如果增加或减少或替换后改变的文本以@结尾,则弹出选择成员界面
2、如果在【某个昵称之间】增加或减少或替换了一些字符,则在@列表中去除此昵称
3、如果是在紧挨着某个昵称之后减少了一些字符,则删除掉文本框中的此昵称,并在@列表中去除此昵称
public class MainActivity extends Activity {
private ArrayList<String> selectedIds = new ArrayList<>();
private ArrayList<SimpleBean> indexs = new ArrayList<SimpleBean>();
private EditText et; protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
et = new EditText(this);
setContentView(et); et.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
//This method is called to notify you that,
// within [s], the [count] characters beginning at [start] are about to be replaced by new text with length [after].
// It is an error to attempt to make changes to s from this callback.
//Log.i("bqt", "【beforeTextChanged】" + s + " " + start + " " + after + " " + count);
} @Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
//This method is called to notify you that,
//within [s], the [count] characters beginning at [start] have just replaced old text that had length [before].
//It is an error to attempt to make changes to [s] from this callback.
//在s中,从start位置开始,有before个字符被count个字符【替换】了
//s 表示改变后输入框中的字符串,start 表示内容是从哪个位置(从0开始)开始改变的
//如果before!=0,代表字符被替换了(可能增加了也可能减少了);如果before=0,可以确定是增加了count个字符 //*************************************************测试代码*****************************************
Log.i("bqt", "【onTextChanged】" + s + " " + start + " " + before + " " + count);
if (before == 0) Log.i("bqt", "【直接增加了一些字符】" + start + " " + count + " " + before);
else {//替换或减少了一些字符
if (count - before > 0) Log.i("bqt", "【替换后增加了一些字符】" + start + " " + count + " " + before);
else if (count - before == 0) Log.i("bqt", "【替换后字符个数没有变】" + start + " " + count + " " + before);
else {
if (count == 0) Log.i("bqt", "【直接减少了一些字符】" + start + " " + count + " " + before);
else Log.i("bqt", "【替换后减少了一些字符】" + start + " " + count + " " + before);
}
} //***********************************************@逻辑代码*******************************************
if (before != 0 && count - before < 0) {//如果是减少了一些字符
for (final SimpleBean sbean : indexs) {
if (start == sbean.end || start == sbean.end - 1) {//如果是在某个昵称之后减少了一些字符
if (selectedIds != null) selectedIds.remove(sbean.userAlias);//如果是的话,在@列表中去除此昵称
Log.i("bqt", "【删除掉文本框中的此昵称】");
et.postDelayed(new Runnable() {
@Override
public void run() {
et.getEditableText().replace(sbean.start, sbean.end, "");//删除掉文本框中的此昵称
}
}, 100);
}
}
} for (SimpleBean sbean : indexs) {
if (start > sbean.start && start < sbean.end) {//是否在【某个昵称之间】增加或减少或替换了一些字符
Log.i("bqt", "【在某个昵称之间_替换_了一些字符】" + sbean.start + " " + start + " " + sbean.end);
if (selectedIds != null) selectedIds.remove(sbean.userAlias);//如果是的话,在@列表中去除此昵称
}
} if (start + count - 1 >= 0 && s.toString().charAt(start + count - 1) == '@') {//如果增加或减少或替换后改变的文本以@结尾
showSingleChoiceDialog();
}
} @Override
public void afterTextChanged(Editable s) {
//Log.i("bqt", "【afterTextChanged】" + s.toString());
indexs.clear();//先清空
//当输入内容后把所有信息封装起来
if (selectedIds != null && selectedIds.size() > 0) {
for (String userAlias : selectedIds) {
String newUserAlias = "@" + userAlias;
int startIndex = et.getText().toString().indexOf(newUserAlias);//注意。这里把@加进去了
int endIndex = startIndex + newUserAlias.length();
indexs.add(new SimpleBean(userAlias, startIndex, endIndex));
Log.i("bqt", userAlias + "的【边界值】" + startIndex + " " + endIndex);
}
Log.i("bqt", "【选择的id有:】" + Arrays.toString(selectedIds.toArray(new String[selectedIds.size()])));
}
}
});
} //单选对话框
public void showSingleChoiceDialog() {
final String[] items = {"白乾涛", "包青天", "baiqiantao"};
AlertDialog dialog = new AlertDialog.Builder(this)//
.setTitle("请选择")//
.setPositiveButton("确定", null).setNegativeButton("取消", null)
.setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (selectedIds == null) selectedIds = new ArrayList<>();
selectedIds.add(items[which]);//先把选择的内容存起来再更改EditText中的内容 //先把选择的内容存起来再更改EditText中的内容,顺序不能反
int index = et.getSelectionStart();//获取光标所在位置
et.getEditableText().insert(index, items[which] + " ");//在光标所在位置插入文字
dialog.dismiss();
}
})
.create();
dialog.show();
} static class SimpleBean {
public int start;
public int end;
public String userAlias; public SimpleBean(String userAlias, int start, int end) {
this.userAlias = userAlias;
this.start = start;
this.end = end;
}
}
}
x
 
1
public class MainActivity extends Activity {
2
   private ArrayList<String> selectedIds = new ArrayList<>();
3
   private ArrayList<SimpleBean> indexs = new ArrayList<SimpleBean>();
4
   private EditText et;
5

6
   protected void onCreate(Bundle savedInstanceState) {
7
      super.onCreate(savedInstanceState);
8
      et = new EditText(this);
9
      setContentView(et);
10

11
      et.addTextChangedListener(new TextWatcher() {
12
         @Override
13
         public void beforeTextChanged(CharSequence s, int start, int count, int after) {
14
            //This method is called to notify you that,
15
            // within [s], the [count] characters beginning at [start] are about to be replaced by new text with length [after].
16
            // It is an error to attempt to make changes to s from this callback.
17
            //Log.i("bqt", "【beforeTextChanged】" + s + "   " + start + "   " + after + "   " + count);
18
         }
19

20
         @Override
21
         public void onTextChanged(CharSequence s, int start, int before, int count) {
22
            //This method is called to notify you that,
23
            //within [s], the [count] characters beginning at [start] have just replaced old text that had length [before].
24
            //It is an error to attempt to make changes to [s] from this callback.
25
            //在s中,从start位置开始,有before个字符被count个字符【替换】了
26
            //s 表示改变后输入框中的字符串,start 表示内容是从哪个位置(从0开始)开始改变的
27
            //如果before!=0,代表字符被替换了(可能增加了也可能减少了);如果before=0,可以确定是增加了count个字符
28

29
            //*************************************************测试代码*****************************************
30
            Log.i("bqt", "【onTextChanged】" + s + "   " + start + "   " + before + "   " + count);
31
            if (before == 0) Log.i("bqt", "【直接增加了一些字符】" + start + " " + count + " " + before);
32
            else {//替换或减少了一些字符
33
               if (count - before > 0) Log.i("bqt", "【替换后增加了一些字符】" + start + " " + count + " " + before);
34
               else if (count - before == 0) Log.i("bqt", "【替换后字符个数没有变】" + start + " " + count + " " + before);
35
               else {
36
                  if (count == 0) Log.i("bqt", "【直接减少了一些字符】" + start + " " + count + " " + before);
37
                  else Log.i("bqt", "【替换后减少了一些字符】" + start + " " + count + " " + before);
38
               }
39
            }
40

41
            //***********************************************@逻辑代码*******************************************
42
            if (before != 0 && count - before < 0) {//如果是减少了一些字符
43
               for (final SimpleBean sbean : indexs) {
44
                  if (start == sbean.end || start == sbean.end - 1) {//如果是在某个昵称之后减少了一些字符
45
                     if (selectedIds != null) selectedIds.remove(sbean.userAlias);//如果是的话,在@列表中去除此昵称
46
                     Log.i("bqt", "【删除掉文本框中的此昵称】");
47
                     et.postDelayed(new Runnable() {
48
                        @Override
49
                        public void run() {
50
                           et.getEditableText().replace(sbean.start, sbean.end, "");//删除掉文本框中的此昵称
51
                        }
52
                     }, 100);
53
                  }
54
               }
55
            }
56

57
            for (SimpleBean sbean : indexs) {
58
               if (start > sbean.start && start < sbean.end) {//是否在【某个昵称之间】增加或减少或替换了一些字符
59
                  Log.i("bqt", "【在某个昵称之间_替换_了一些字符】" + sbean.start + " " + start + " " + sbean.end);
60
                  if (selectedIds != null) selectedIds.remove(sbean.userAlias);//如果是的话,在@列表中去除此昵称
61
               }
62
            }
63

64
            if (start + count - 1 >= 0 && s.toString().charAt(start + count - 1) == '@') {//如果增加或减少或替换后改变的文本以@结尾
65
               showSingleChoiceDialog();
66
            }
67
         }
68

69
         @Override
70
         public void afterTextChanged(Editable s) {
71
            //Log.i("bqt", "【afterTextChanged】" + s.toString());
72
            indexs.clear();//先清空
73
            //当输入内容后把所有信息封装起来
74
            if (selectedIds != null && selectedIds.size() > 0) {
75
               for (String userAlias : selectedIds) {
76
                  String newUserAlias = "@" + userAlias;
77
                  int startIndex = et.getText().toString().indexOf(newUserAlias);//注意。这里把@加进去了
78
                  int endIndex = startIndex + newUserAlias.length();
79
                  indexs.add(new SimpleBean(userAlias, startIndex, endIndex));
80
                  Log.i("bqt", userAlias + "的【边界值】" + startIndex + "  " + endIndex);
81
               }
82
               Log.i("bqt", "【选择的id有:】" + Arrays.toString(selectedIds.toArray(new String[selectedIds.size()])));
83
            }
84
         }
85
      });
86
   }
87

88
   //单选对话框
89
   public void showSingleChoiceDialog() {
90
      final String[] items = {"白乾涛", "包青天", "baiqiantao"};
91
      AlertDialog dialog = new AlertDialog.Builder(this)//
92
            .setTitle("请选择")//
93
            .setPositiveButton("确定", null).setNegativeButton("取消", null)
94
            .setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() {
95
               public void onClick(DialogInterface dialog, int which) {
96
                  if (selectedIds == null) selectedIds = new ArrayList<>();
97
                  selectedIds.add(items[which]);//先把选择的内容存起来再更改EditText中的内容
98

99
                  //先把选择的内容存起来再更改EditText中的内容,顺序不能反
100
                  int index = et.getSelectionStart();//获取光标所在位置
101
                  et.getEditableText().insert(index, items[which] + " ");//在光标所在位置插入文字
102
                  dialog.dismiss();
103
               }
104
            })
105
            .create();
106
      dialog.show();
107
   }
108

109
   static class SimpleBean {
110
      public int start;
111
      public int end;
112
      public String userAlias;
113

114
      public SimpleBean(String userAlias, int start, int end) {
115
         this.userAlias = userAlias;
116
         this.start = start;
117
         this.end = end;
118
      }
119
   }
120
}

2018-5-22

监听内容变化 TextWatcher @功能的更多相关文章

  1. edittext 监听内容变化

    给EditText追加ChangedListener可以监听EditText内容变化的监听 如图是效果图  类似于过滤的一种实现 1  布局也就是一个EditText,当EditText内容发生变化时 ...

  2. DOMNodeInserted,DOMNodeRemoved 和监听内容变化插件

    元素的增加 删除 及事件监听 <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...

  3. 监听EditText变化---TextWatcher 类用法详解

    http://www.cnblogs.com/yjing0508/p/5316985.html TextWatcher textWatcher = new TextWatcher() { @Overr ...

  4. 009——VUE中watch监听属性变化实现类百度搜索栏功能

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  5. node.js监听文件变化

    前言 随着前端技术的飞速发展,前端开发也从原始的刀耕火种,向着工程化效率化的方向发展.在各种开发框架之外,打包编译等技术也是层出不穷,开发体验也是越来越好.例如HMR,让我们的更新可以即时可见,告别了 ...

  6. iOS开发之--为UITextField监听数值变化的三种方法

    项目中有个验证码输入直接验证跳转页面,用的RAC来监听textfield的输入值,如下: @weakify(self); [self.codeView.textField.rac_textSignal ...

  7. vue项目如何监听窗口变化,达到页面自适应?

    [自适应]向来是前端工程师需要解决的一大问题--即便作为当今非常火热的vue框架,也无法摆脱--虽然elementui.iview等开源UI组件库层出不穷,但官方库毕竟不可能满足全部需求,因此我们可以 ...

  8. Angular.js中使用$watch监听模型变化

    $watch简单使用 $watch是一个scope函数,用于监听模型变化,当你的模型部分发生变化时它会通知你. $watch(watchExpression, listener, objectEqua ...

  9. $scope.$watch()——监听数据变化

    $scope.$watch(watchFn, watchAction, [deepWatch]):监听数据变化,三个参数 --watchFn:监听的对象,一个带有Angular 表达式或者函数的字符串 ...

随机推荐

  1. Python爬虫笔记(一)

    个人笔记,仅适合个人使用(大部分摘抄自python修行路) 1.爬虫Response的内容 便是所要获取的页面内容,类型可能是HTML,Json(json数据处理链接)字符串,二进制数据(图片或者视频 ...

  2. BASH 的调试技巧

    平时在写 BASH 脚本时,总是会碰到让人抓狂的 BUG.和 C/C++ 这么丰富的调试工具相比,BASH 又有什么调试手段呢? 1 echo/print (普通技) 打印一些变量,或者提示信息.这应 ...

  3. windows关闭aslr办法

    关闭aslr方便调试分析. 转:https://www.52pojie.cn/thread-377450-1-1.html windows关闭aslr办法 如 @Hmily  前辈所说, Window ...

  4. 洛谷——P2393 yyy loves Maths II

    P2393 yyy loves Maths II 题目背景 上次蒟蒻redbag可把yyy气坏了,yyy说他只是小学生,蒟蒻redbag这次不坑他了. 题目描述 redbag给了yyy很多个数,要yy ...

  5. Linux下Makefile学习笔记

    makefile 可以用于编译和执行多个C/C++源文件和头文件. (1) #include "file.h" 和 #include <file.h> 的区别 #inc ...

  6. braft初探

    接上一篇<brpc初探>. 什么是RAFT 看内部一个开源项目的时候,一开始我以为他们自己实现了raft协议.但是看了代码之后,发现用的是braft.因为在我们自己bg里一直在提paxos ...

  7. shell脚本基本用法

    下面是一些简单常用的脚本,工作中可能会用到,记录一下. #!/usr/bin/env bash #变量[=两边不要有空格], 在使用的时候需要用${变量名} 或者是$变量名 name="sa ...

  8. Linux-数据库1

    数据库介绍 数据库(database,DB)是指长期存储在计算机内的,有组织,可共享的数据的集合.数据库中的数据按一定的数学模型组织.描述和存储,具有较小的冗余,较高的数据独立性和易扩展性,并可为各种 ...

  9. 【BZOJ 3747】 3747: [POI2015]Kinoman (线段树)

    3747: [POI2015]Kinoman Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 830  Solved: 338 Description ...

  10. 「NOI2017」游戏

    「NOI2017」游戏 题目描述 小 L 计划进行 \(n\) 场游戏,每场游戏使用一张地图,小 L 会选择一辆车在该地图上完成游戏. 小 L 的赛车有三辆,分别用大写字母 \(A\).\(B\).\ ...