EditText输入内容拦截和监听删除

hackernew
发布于 2021-2-26 10:30
浏览
0收藏

前言


有时候我们会有一些特殊的需求,需要对输入框进行特殊的处理,比如:

  • 对输入内容去除特殊字符操作,或拦截输入内容提交
  • 监听软件盘删除按钮点击事件,并能在一定条件下拦截
  • 监听输入框文字粘贴、复制、全选等


拦截输入内容提交


对于 EditText 的文字监听,我们通常使用的是添加文字变化监听 addTextChangedListener(watcher) ,通过文字变化监听 TextWatcher 对文字作处理,处理后重新设置文字。需要处理死循环的问题(类似递归,要有终止条件)。

其实可以在输入文字提交之前,还未显示到界面时,就对文字进行处理,需要重写方法

    @Override
    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
        return new MyInputConnection(super.onCreateInputConnection(outAttrs), false);
    }

  • 1.
  • 2.
  • 3.
  • 4.

创建自己的输入连接(InputConnection),在 commitText() 方法中返回 false,提交的内容将会被拦截。
具体代码见最后。

 

监听软件盘删除按钮点击事件


对于软键盘删除按键的监听,通常我们使用 setOnKeyListener(l) ,但是在一些非常规特殊情况下不那么好用,比如多行输入时屏蔽换行。

 

监听输入框文字粘贴、复制、全选等


监听输入框文字粘贴、复制、全选等操作,需要重写 onTextContextMenuItem(id) 方法,通过 id 区分操作,重写对应的逻辑。都有哪些操作,也即都有哪些 id 呢?ctrl + 鼠标左键点击 super.onTextContextMenuItem(id) ,查看源码,找到了以下 id:

     *     static final int ID_SELECT_ALL = android.R.id.selectAll;
     *     static final int ID_UNDO = android.R.id.undo;
     *     static final int ID_REDO = android.R.id.redo;
     *     static final int ID_CUT = android.R.id.cut;
     *     static final int ID_COPY = android.R.id.copy;
     *     static final int ID_PASTE = android.R.id.paste;
     *     static final int ID_SHARE = android.R.id.shareText;
     *     static final int ID_PASTE_AS_PLAIN_TEXT = android.R.id.pasteAsPlainText;
     *     static final int ID_REPLACE = android.R.id.replaceText;
     *     static final int ID_ASSIST = android.R.id.textAssist;
     *     static final int ID_AUTOFILL = android.R.id.autofill;
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

由于源码里并没有开放这些 id 常量,所以只能用 android.R.id.copy 这样的 id。

 

code

/**
 * 扩展输入框。
 * 可拦截:
 *   软件盘删除按钮点击事件;
 *   输入框内容提交;
 *   长按文字菜单选项点击事件(复制、粘贴、全选等)
 */
public class ExtendEditText extends AppCompatEditText {

    public ExtendEditText(Context context) {
        super(context);
    }

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

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


    /**
     * 监听长按后选项菜单
     * @param id
     *     static final int ID_SELECT_ALL = android.R.id.selectAll;
     *     static final int ID_UNDO = android.R.id.undo;
     *     static final int ID_REDO = android.R.id.redo;
     *     static final int ID_CUT = android.R.id.cut;
     *     static final int ID_COPY = android.R.id.copy;
     *     static final int ID_PASTE = android.R.id.paste;
     *     static final int ID_SHARE = android.R.id.shareText;
     *     static final int ID_PASTE_AS_PLAIN_TEXT = android.R.id.pasteAsPlainText;
     *     static final int ID_REPLACE = android.R.id.replaceText;
     *     static final int ID_ASSIST = android.R.id.textAssist;
     *     static final int ID_AUTOFILL = android.R.id.autofill;
     * @return
     */
    @Override
    public boolean onTextContextMenuItem(int id) {

        boolean handled = false;
        if (mOnTextMenuItemClickListener != null) {
            handled = mOnTextMenuItemClickListener.onTextMenuItemClick(id);
        }

        return handled || super.onTextContextMenuItem(id);
    }

    private OnTextMenuItemClickListener mOnTextMenuItemClickListener;

    /**
     * 设置文字菜单选项点击监听,用于监听粘贴、全选、复制等操作,可以重写这些操作逻辑。
     */
    public void setOnTextMenuItemClickListener(OnTextMenuItemClickListener onTextMenuItemClickListener) {
        mOnTextMenuItemClickListener = onTextMenuItemClickListener;
    }

    /**
     * 文字菜单选项点击监听
     */
    public interface OnTextMenuItemClickListener {
        boolean onTextMenuItemClick(int id);
    }

    /**
     * 输入法
     *
     * @param outAttrs
     * @return
     */
    @Override
    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
        return new MyInputConnection(super.onCreateInputConnection(outAttrs), false);
    }


    private int count;

    class MyInputConnection extends InputConnectionWrapper implements
            InputConnection {

        public MyInputConnection(InputConnection target, boolean mutable) {
            super(target, mutable);
        }


        /**
         * 对输入的内容进行拦截
         *
         * @param text
         * @param newCursorPosition
         * @return
         */
        @Override
        public boolean commitText(CharSequence text, int newCursorPosition) {

            if (mOnCommitTextListener != null) {
                if (!mOnCommitTextListener.onCommitText(text, newCursorPosition)) {
                    return false;
                }
            }

//            // 只能输入汉字
//            if (!text.toString().matches("[\u4e00-\u9fa5]+") && !text.toString().matches("[a-zA-Z]+") && !text.toString().matches("[0-9]")) {
//                ToastUtil.ToastShow(getContext(), "只能输入数字和字母和汉字");
//                return false;
//            }
//
//
//            tips(text.toString());
//
//            if (count > 16) {
//                ToastUtil.ToastShow(getContext(), "最多16个字符");
//                return false;
//            }

            return super.commitText(text, newCursorPosition);
        }

        private void tips(String append) {
            count = 0;

            String text = getText().toString();
            for (int i = 0; i < text.length(); i++) {
                String a = String.valueOf(text.charAt(i));
                if (a.matches("[\u4e00-\u9fa5]+")) {
                    count = count + 2;
                } else {
                    count = count + 1;
                }
            }


            for (int i = 0; i < append.length(); i++) {
                String a = String.valueOf(append.charAt(i));
                if (a.matches("[\u4e00-\u9fa5]+")) {
                    count = count + 2;
                } else {
                    count = count + 1;
                }
            }


        }

        @Override
        public boolean sendKeyEvent(KeyEvent event) {
            if (event.getAction() == KeyEvent.ACTION_DOWN
                    && event.getKeyCode() == KeyEvent.KEYCODE_DEL) {
                if (mOnCommitTextListener != null) {
                    if (mOnCommitTextListener.onDeleteClick()) { // 软键盘删除按钮点击事件拦截。
                        return true;
                    }
                }
            }
            return super.sendKeyEvent(event);
        }

        @Override
        public boolean deleteSurroundingText(int beforeLength, int afterLength) {
            if (beforeLength == 1 && afterLength == 0) {
                return sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN,
                        KeyEvent.KEYCODE_DEL))
                        && sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP,
                        KeyEvent.KEYCODE_DEL));
            }
            return super.deleteSurroundingText(beforeLength, afterLength);
        }
    }


    private OnCommitTextListener mOnCommitTextListener;

    public void setOnCommitTextListener(OnCommitTextListener onCommitTextListener) {
        mOnCommitTextListener = onCommitTextListener;
    }

    public interface OnCommitTextListener {

        /**
         * 输入文字监听回调。可以对输入文字进行拦截,处理后再显示(比如去掉特殊字符)。
         * @param text
         * @param newCursorPosition
         * @return
         */
        boolean onCommitText(CharSequence text, int newCursorPosition);

        /**
         * 当软键盘删除按钮点击时的回调方法。
         * @return true,拦截;false,默认
         */
        boolean onDeleteClick();
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
  • 142.
  • 143.
  • 144.
  • 145.
  • 146.
  • 147.
  • 148.
  • 149.
  • 150.
  • 151.
  • 152.
  • 153.
  • 154.
  • 155.
  • 156.
  • 157.
  • 158.
  • 159.
  • 160.
  • 161.
  • 162.
  • 163.
  • 164.
  • 165.
  • 166.
  • 167.
  • 168.
  • 169.
  • 170.
  • 171.
  • 172.
  • 173.
  • 174.
  • 175.
  • 176.
  • 177.
  • 178.
  • 179.
  • 180.
  • 181.
  • 182.
  • 183.
  • 184.
  • 185.
  • 186.
  • 187.
  • 188.
  • 189.
  • 190.
  • 191.
  • 192.
  • 193.
  • 194.
  • 195.

 

 

分类
已于2021-2-26 10:30:07修改
收藏
回复
举报


回复
    相关推荐