zoukankan      html  css  js  c++  java
  • 监听内容变化 TextWatcher @功能

    监听多个TextView的内容变化

    使用示例
    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;
    	}
    }

    仿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;
          }
       }
    }

    2018-5-22




  • 相关阅读:
    男子利用POS机帮人非法套现1576万余元被起诉
    套现花样很多 弄不好成了诈骗
    刀尖上的无本生意 信用卡套现投资盛行
    新三板是什么—新三板科普知识讲堂
    Android注入事件的三种方法比较
    当今最流行的Node.js应用开发框架简介
    安卓WindowManager注入事件如何跳出进程间安全限制
    伟大创意检验10要
    初创互联网公司简明创业指南
    根据Unix哲学来编写你的HTML5 Websocket服务器来实现全双工通信
  • 原文地址:https://www.cnblogs.com/baiqiantao/p/6802979.html
Copyright © 2011-2022 走看看