美文网首页Android软键盘程序员
从华为P9软键盘删除时无响应到InputConnectionWr

从华为P9软键盘删除时无响应到InputConnectionWr

作者: 阿敏其人 | 来源:发表于2017-02-13 22:12 被阅读318次

    一、起因

    一个需求,类似微信将群,即多选好友之后,在页面有一个列表显示已选好友的头像,这是如果Edittext内容为空并且按下软键盘的删除键,第一次让头像变灰,第二次则删减最后一个已经勾选的成员。

    效果大概如下图:

    联动.gif

    实现就实现呗,按道理我们搞一个Edittext,然后按照如下代码,应该是没什么问题的

            mEt.setOnKeyListener(new View.OnKeyListener() {
                @Override
                public boolean onKey(View v, int keyCode, KeyEvent event) {
                    if (keyCode == KeyEvent.KEYCODE_DEL && event.getAction() == KeyEvent.ACTION_DOWN) {
                        String content = mEt.getText().toString();
                        if (TextUtils.isEmpty(content)) {
                            mTvResult.setText("原生Et 无内容");
                        }else{
                            mTvResult.setText("原生Et DEL_DOWN:  "+content);
                        }
                    }
                    return false;
                }
            });
    

    但是,部分机型,比如华为P9,当Edittext内容为空时,他就根本无法响应软键盘的删除监听,搞事情!

    二、经过 (解决办法)

    先看一些解决问题后的代码:

    MainActivity

    public class MainActivity extends AppCompatActivity {
    
        private EditText mEt;
        private ZanyEditText mZanyEt;
        private TextView mTvResult;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            mEt = (EditText) findViewById(R.id.mEt);
            mZanyEt = (ZanyEditText) findViewById(R.id.mZanyEt);
            mTvResult = (TextView) findViewById(R.id.mTvResult);
    
    
            mEt.setOnKeyListener(new View.OnKeyListener() {
                @Override
                public boolean onKey(View v, int keyCode, KeyEvent event) {
                    if (keyCode == KeyEvent.KEYCODE_DEL && event.getAction() == KeyEvent.ACTION_DOWN) {
                        String content = mEt.getText().toString();
                        if (TextUtils.isEmpty(content)) {
                            mTvResult.setText("原生Et 无内容");
                        }else{
                            mTvResult.setText("原生Et DEL_DOWN:  "+content);
                        }
                    }
                    return false;
                }
            });
    
            mZanyEt.setOnKeyListener(new View.OnKeyListener() {
                @Override
                public boolean onKey(View v, int keyCode, KeyEvent event) {
                    if (keyCode == KeyEvent.KEYCODE_DEL && event.getAction() == KeyEvent.ACTION_DOWN) {
                        String content = mZanyEt.getText().toString();
                        if (TextUtils.isEmpty(content)) {
                            mTvResult.setText("ZanyEt 无内容");
                        }else{
                            mTvResult.setText("ZanyEt DEL_DEL_DOWN:  "+content);
                        }
                    }
                    return false;
                }
            });
    
        }
    }
    

    .
    .
    布局代码

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        android:id="@+id/activity_main"
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        android:orientation="vertical"
        tools:context="com.amqr.editdemo.MainActivity">
    
    
        <EditText
            android:id="@+id/mEt"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:text="原生"
    
            />
    
        <com.amqr.editdemo.ZanyEditText
            android:id="@+id/mZanyEt"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="重写"
            />
    
        <TextView
            android:id="@+id/mTvResult"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="30dp"
            android:text="RESULT"
            />
    
    </LinearLayout>
    

    .
    .
    .
    核心文件
    ZanyEditText

    public class ZanyEditText extends EditText {
        private OnDelKeyEventListener delKeyEventListener;
        public ZanyEditText(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
        public ZanyEditText(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
        public ZanyEditText(Context context) {
            super(context);
        }
        @Override
        public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
            return new ZanyInputConnection(super.onCreateInputConnection(outAttrs),
                    true);
        }
        private class ZanyInputConnection extends InputConnectionWrapper {
            public ZanyInputConnection(InputConnection target, boolean mutable) {
                super(target, mutable);
            }
            @Override
            public boolean sendKeyEvent(KeyEvent event) {
                if (event.getAction() == KeyEvent.ACTION_DOWN
                        && event.getKeyCode() == KeyEvent.KEYCODE_DEL) {
                    if (delKeyEventListener != null) {
                        delKeyEventListener.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);
            }
        }
        /**
         * EditText 删除回调
         */
        public void setDelKeyEventListener(OnDelKeyEventListener delKeyEventListener) {
            this.delKeyEventListener = delKeyEventListener;
        }
        public interface OnDelKeyEventListener {
            void onDeleteClick();
        }
    }
    

    具体原因不是为什么P9等部分机器身上无法响应删除监听,接下来我们来看看下面这几点:

    1、Edittext继承自TextView

    2、翻看TextView的代码,里面有一个叫做InputConnection的东西,看起是什么输入连接的意思。

    3、InputConnectionWrapper 是 InputConnection的实现类,我们继承这个包装类并且实现 sendKeyEvent 和 deleteSurroundingText 两个方法一下。

    InputConnectionWrapper文档

    --- sendKeyEvent

    Send a key event to the process that is currently attached through this input connection.

    将关键事件发送到当前通过此连接的进程。

    其实我觉得大概是说怎么处理当前这个软件键的事件

    --- deleteSurroundingText

    Delete beforeLength characters of text before the current cursor position, and delete afterLength characters of text after the current cursor position, excluding the selection.

    .
    .
    .
    回顾核心代码

    private class ZanyInputConnection extends InputConnectionWrapper {
            public ZanyInputConnection(InputConnection target, boolean mutable) {
                super(target, mutable);
            }
            @Override
            public boolean sendKeyEvent(KeyEvent event) {
                if (event.getAction() == KeyEvent.ACTION_DOWN
                        && event.getKeyCode() == KeyEvent.KEYCODE_DEL) {
                    if (delKeyEventListener != null) {
                        delKeyEventListener.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);
            }
        }
    

    Activity的处理下面的代码就可以顺利监听到删除键了。

      mZanyEt.setOnKeyListener(new View.OnKeyListener() {
                @Override
                public boolean onKey(View v, int keyCode, KeyEvent event) {
                    if (keyCode == KeyEvent.KEYCODE_DEL && event.getAction() == KeyEvent.ACTION_DOWN) {
                        String content = mZanyEt.getText().toString();
                        if (TextUtils.isEmpty(content)) {
                            mTvResult.setText("ZanyEt 无内容");
                        }else{
                            mTvResult.setText("ZanyEt DEL_DEL_DOWN:  "+content);
                        }
                    }
                    return false;
                }
            });
    

    上文ZanyEditText出处

    三、结果

    结果无非就是可以监听到了呗。

    相关文章

      网友评论

      • 不想_忘记:ZanyEditText 类中,EditText 删除回调 setDelKeyEventListener 好像没使用到吧?

      本文标题:从华为P9软键盘删除时无响应到InputConnectionWr

      本文链接:https://www.haomeiwen.com/subject/ljttwttx.html