禁止表情输入和长度限制

来源:互联网 发布:刘丹青 知乎 编辑:程序博客网 时间:2024/05/16 15:43
  • 前言

    现在好多人聊天喜欢输入表情, 所以在开发中测试人员也习惯去测试编辑框输入表情,经常出现数据提交失败。然而好多的编辑并不需要表情的或表情符时,这时我们就需要去禁止用户输入表情。
  • 问题

    当我们使用setFilters方法过滤表情输入之后,而且通过maxLength增加文本输入字数限制时,两个就不能同时生效了。

  • 原因

    因为默认EditTextView是有一个关于maxLength的过滤器的,我们通过setFilters的参数是一个新数组,就覆盖了原来的长度过滤器,所以maxLength就不能生效了,源码:
    这里写图片描述

  • 解决办法

    解决办法很简单,就是在设置过滤器时把原来的过滤器拼接到新的数组中去,然后setFilters就ok了:
    editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(maxLength), emojiFilter});
    很多人马上就发现这个有个缺点,就是xml里面配置的maxLength就没什么用了,每次都需要在代码中去动态配置这个长度限制。其实解决这个问题也很简单:
    方法1:通过反射获取maxLength属性的值,这里我就不讲了。
    方法2:我们重点讲怎么通过obtainStyledAttributes获取到xml中到maxLength属性值,大家经常自定义属性就知道obtainStyledAttributes可以通过两个参数获取属性值,AttributeSet和属性id数组:
    这里写图片描述
    属性attrs我们可以直接在构造方法里面获取,res属性int数组定义成maxLength属性数组:
    int[] res = new int[]{android.R.attr.maxLength};
    好了,然后我们再去使用我们自定义的EditText,就可以禁止表情输入而且可以通过xml的maxLength设置文本输入长度了。

  • 源码

    代码很简单:
    public class EmojiEditText extends EditText {
    int[] res = new int[]{android.R.attr.maxLength};
    private int maxLength;

    InputFilter emojiFilter = new InputFilter() {
    Pattern emoji = Pattern.compile(“[\ud83c\udc00-\ud83c\udfff]|[\ud83d\udc00-\ud83d\udfff]|[\u2600-\u27ff]”,
    Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE);

    @Overridepublic CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {    //正则表达是的检测有些Emoji表情检测不到,所以注释掉了    //Matcher emojiMatcher = emoji.matcher(source);   // if (emojiMatcher.find()) {      //  Toast.makeText(getContext(), "不支持输入表情", 0).show();      //  return "";    //}    if(containsEmoji(source.toString())){        Toast.makeText(getContext(), "不支持输入表情", 0).show();        return "";    }    return null;}

    };

    public EmojiEditText(Context context) {
    super(context);
    init(context, null);
    }

    public EmojiEditText(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context, attrs);
    }

    public EmojiEditText(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);

    init(context, attrs);

    }

    public EmojiEditText(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
    init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
    TypedArray a = context.obtainStyledAttributes(attrs, res);
    maxLength = a.getInt(0, Integer.MAX_VALUE);
    a.recycle();
    setFilters(new InputFilter[]{new InputFilter.LengthFilter(maxLength), emojiFilter});
    }
    /**

    • 检测是否有emoji表情
      *
    • @param source
    • @return
      */
      public boolean containsEmoji(String source) {
      int len = source.length();
      for (int i = 0; i < len; i++) {
      char codePoint = source.charAt(i);
      if (!isEmojiCharacter(codePoint)) { //如果不能匹配,则该字符是Emoji表情
      return true;
      }
      }
      return false;
      }

    /**

    • 判断是否是Emoji
      *
    • @param codePoint 比较的单个字符
    • @return
      */
      private boolean isEmojiCharacter(char codePoint) {
      return (codePoint == 0x0) || (codePoint == 0x9) || (codePoint == 0xA) ||
      (codePoint == 0xD) || ((codePoint >= 0x20) && (codePoint <= 0xD7FF)) ||
      ((codePoint >= 0xE000) && (codePoint <= 0xFFFD)) || ((codePoint >= 0x10000)
      && (codePoint <= 0x10FFFF));
      }

}