一、起因
一个需求,类似微信将群,即多选好友之后,在页面有一个列表显示已选好友的头像,这是如果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 两个方法一下。
--- 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;
}
});
三、结果
结果无非就是可以监听到了呗。
网友评论