监听多个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
18
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
19
20
}
21
22
23
public void onTextChanged(CharSequence s, int start, int before, int count) {
24
25
}
26
27
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
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
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
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
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