监听内容变化 TextWatcher @功能
监听多个TextView的内容变化
TextWatcherUtils.addTextChangedListener(isAllNotEmpty -> btnLogin.setEnabled(isAllNotEmpty), etCode, etPhone);
x
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;
}
}
/**
* 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;
}
}
仿QQ、微信、钉钉的@功能 案例
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
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;
}
}
}
监听内容变化 TextWatcher @功能的更多相关文章
- edittext 监听内容变化
给EditText追加ChangedListener可以监听EditText内容变化的监听 如图是效果图 类似于过滤的一种实现 1 布局也就是一个EditText,当EditText内容发生变化时 ...
- DOMNodeInserted,DOMNodeRemoved 和监听内容变化插件
元素的增加 删除 及事件监听 <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...
- 监听EditText变化---TextWatcher 类用法详解
http://www.cnblogs.com/yjing0508/p/5316985.html TextWatcher textWatcher = new TextWatcher() { @Overr ...
- 009——VUE中watch监听属性变化实现类百度搜索栏功能
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- node.js监听文件变化
前言 随着前端技术的飞速发展,前端开发也从原始的刀耕火种,向着工程化效率化的方向发展.在各种开发框架之外,打包编译等技术也是层出不穷,开发体验也是越来越好.例如HMR,让我们的更新可以即时可见,告别了 ...
- iOS开发之--为UITextField监听数值变化的三种方法
项目中有个验证码输入直接验证跳转页面,用的RAC来监听textfield的输入值,如下: @weakify(self); [self.codeView.textField.rac_textSignal ...
- vue项目如何监听窗口变化,达到页面自适应?
[自适应]向来是前端工程师需要解决的一大问题--即便作为当今非常火热的vue框架,也无法摆脱--虽然elementui.iview等开源UI组件库层出不穷,但官方库毕竟不可能满足全部需求,因此我们可以 ...
- Angular.js中使用$watch监听模型变化
$watch简单使用 $watch是一个scope函数,用于监听模型变化,当你的模型部分发生变化时它会通知你. $watch(watchExpression, listener, objectEqua ...
- $scope.$watch()——监听数据变化
$scope.$watch(watchFn, watchAction, [deepWatch]):监听数据变化,三个参数 --watchFn:监听的对象,一个带有Angular 表达式或者函数的字符串 ...
随机推荐
- .NET基本权限系统框架源代码
DEMO下载地址: 百度网盘:http://pan.baidu.com/s/147ilj http://download.csdn.net/detail/shecixiong/5372895 一.开发 ...
- spring配置多数据源——mybatis
这篇文章是配置mybatis多数据源文章,如果是hibernate的话也是没什么影响,配置都是差不多的. 在这家公司上班差不多一星期了,不小心点开配置文件一看这项目配置了两个数据源,蒙了. 之后上网查 ...
- 图形管线之旅 Part6
原文:<A trip through the Graphics Pipeline 2011> 翻译:往昔之剑 转载请注明出处 欢迎回来.这次我们去看看三角形的光栅化.但在光栅化三角 ...
- 火焰图&perf命令
最近恶补后端技术,发现还是很多不懂,一直写业务逻辑容易迷失,也没有成长.自己做系统,也习惯用自己已知的知识来解决,以后应该多点调研,学到更多的东西应用起来. 先学一个新的性能分析命令. NAME pe ...
- python 多进程操作
由于python 多线程是无法在多核上发挥优势的,所以才用多进程的方式来折中将这个问题解决. from multiprocessing import Pool import os def f(x): ...
- 【BZOJ 1272】 1272: [BeiJingWc2008]Gate Of Babylon (容斥原理+卢卡斯定理)
1272: [BeiJingWc2008]Gate Of Babylon Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 254 Solved: 12 ...
- [NOI2009]诗人小G --- DP + 决策单调性
[NOI2009]诗人小G 题目描述: 小G是一个出色的诗人,经常作诗自娱自乐. 但是,他一直被一件事情所困扰,那就是诗的排版问题. 一首诗包含了若干个句子,对于一些连续的短句,可以将它们用空格隔开并 ...
- [BZOJ3992][SDOI2015]序列统计(DP+原根+NTT)
3992: [SDOI2015]序列统计 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 1888 Solved: 898[Submit][Statu ...
- bzoj 1030
dp[i][j] 表示,在AC自动机中,从根节点开始,走了i条边,并且经过的点不包含危险节点,走到了j节点的路径数. 收获: 1.正难则反 2.一个字符串不包含给定pattern中的任何一个,则该字符 ...
- 2015 UESTC 数据结构专题C题 秋实大哥与快餐店 字典树
C - 秋实大哥与快餐店 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/contest/show/59 ...