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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了text 从华为P9软键盘删除时无响应到InputConnectionWrapper相关的知识,希望对你有一定的参考价值。

从华为P9软键盘删除时无响应到InputConnectionWrapper
96  阿敏其人 
2017.02.13 22:12* 字数 457 阅读 786评论 1喜欢 3
一、起因
一个需求,类似微信将群,即多选好友之后,在页面有一个列表显示已选好友的头像,这是如果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出处

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

以上是关于text 从华为P9软键盘删除时无响应到InputConnectionWrapper的主要内容,如果未能解决你的问题,请参考以下文章

禁止移动端input弹出软键盘

移动端界面devicePixelRatio问题与移动端软键盘keyCode

手机端浏览器中的html搜索框如何响应软键盘搜索按钮事件?

移动端 Web 页 input 控制软键盘

JS自动让手机调出软键盘,进行输入

Android基础篇 监听软键盘回车事件以及回车响应两次