监听内容变化 TextWatcher @功能

摘要:
监听多个TextView的内容变化使用示例TextWatcherUtils.addTextChangedListener(isAllNotEmpty->btnLogin.setEnabled(isAllNotEmpty),etCode,etPhone);x1TextWatcherUtils.addTextChangedListener(isAllNotEmpty->btnLogin.setEnab

监听多个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

来自为知笔记(Wiz)

免责声明:文章转载自《监听内容变化 TextWatcher @功能》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇无法识别的属性“targetFramework”的解决方法hello MemSQL 入门安装演示样例下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

Debian 命令行方式配置网络

确保未在文件/etc/network/interfaces中手动配置网络,即应删除上述1和2中配置的内容。打开nmtui的图形界面并直接进行配置。当然,您也可以在此处设置无线连接。...

Datax3.0使用说明

任务是DataX作业的最小单位。每个任务负责一些数据的同步。DataX的调度决策思想是:-DataXJob根据数据库和表划分为100个任务。...

Notepad++正则表达式查找替换文本中文字符

测试需求测试工具中xml配置文件中的注释字段包含中文字符。Win10系统中使用的工具中偶尔会出现中文乱码,导致配置文件无效。解决方案是将配置文件中的中文注释替换为英文注释,或者直接替换和删除。如何查找和删除配置文件中的汉字?“记事本”中使用正则表达式[^x00 xff]来匹配汉字。替换完成如下3。所有汉字已被替换。...

layui table 打印表格

例如,layui的表单打印方法是将表单的数据重新组合成新页面,但它只能打印当前页面的内容。仅仅说实话是不够的。我整个上午都找到了一些,并说他们自己换了,但他们并不满意。这没用。我只能打印当前页面的内容。我的想法是编写一个函数,传递显示的列和要打印的数据,然后直接打印。不要胡说八道。直接转到代码。...

svn文件冲突,树冲突详解

文件冲突当两名或更多开发人员修改了同一个文件中相邻或相同的行时就会发生文件冲突。这个操作会出现一个对话框,列出文件夹下所有有冲突的文件,你可以选择将哪些标记成已解决。因此即使它是树冲突的一部分,却既不能显示冲突的叠加图标也不能通过右键单击来解决冲突。在此案例中,使用冲突编辑对话框中的删除按钮进行清理并将冲突标记为已解决。Foo.c被标记为删除并且产生一个树冲...

CefSharp 浏览器核心,爬虫

CefSharp是什么Aframeworkforembeddingweb-browsing-likecapabilitiestoastandard.NETapplication(WPForWindowsForms).Asetofhigh-levelcustomcontrolstomakeitreasonablyeasytointegratethesecapa...