项目中有一个需求,类似小红书app笔记评论,实现的效果如下(勉强可以看清吧)
点击评论视图外部,隐藏评论视图并关闭软键盘
在activity的dispatchTouchEvent
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
//inputMethodShowing为定义的软键盘打开的标志
if (inputMethodShowing && isOutBottomLayout(ev)) {
hideInputMethod();
return true;
}
}
return super.dispatchTouchEvent(ev);
}
判断touch事件是否在评论视图外
public boolean isOutBottomLayout(MotionEvent event) {
if (bottom_layout != null) {
int[] leftTop = {0, 0};
//获取bottomlayout当前的location位置
bottom_layout.getLocationInWindow(leftTop);
int left = leftTop[0];
int top = leftTop[1];
int bottom = top + bottom_layout.getHeight();
int right = left + bottom_layout.getWidth();
if (event.getX() > left && event.getX() < right
&& event.getY() > top && event.getY() < bottom) {
// 点击在bottomlayout内,保留事件
return false;
} else {
return true;
}
}
return false;
}
点击返回键或点击输入法上的收起软键盘按钮,关闭软键盘并隐藏评论视图
罗升阳前辈相关博客:https://blog.csdn.net/luoshengyang/article/details/6882903
当软键盘打开时,第一次点击返回键,不会走onBackPress和onKeyDown方法,会关闭软键盘,当第二次点击返回键时才会调用,原因时,当点击返回键时,会先调用view的dispatchKeyEventPreIme方法,在把返回事件传递给输入法处理之前先派发给dispachKeyEventPreIme方法,当其不进行处理时,才会交给输入法处理,输入法处理会关闭软键盘,进而事件被消费不再往下传递。
通过dispatchKeyEventPreIme
方法监听返回键(如果有输入法存在,那么按键消息首先会被派发到输入法窗口,如果想在输入法截获消息之前处理该消息,那么可以重载该函数)
关于此方法可参考:https://blog.csdn.net/zjmdp/article/details/7706520
https://blog.csdn.net/siobhan/article/details/8268543
这个方法可以在软键盘打开状态时监听到返回键的,可以做自己的一些处理
但是,这个方法只能监听到返回键,想要的效果是当软键盘隐藏时,底部的评论视图就隐藏,就忽略了一种情况:当点击软键盘上的“v”隐藏软键盘按键时,底部的评论视图还是没有隐藏掉,所以只能作罢,再找其它的方法。
public class SoftKeyboardSizeWatchLayout extends ConstraintLayout {
public SoftKeyboardSizeWatchLayout(Context context) {
super(context);
}
public SoftKeyboardSizeWatchLayout(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public SoftKeyboardSizeWatchLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public interface OnResizeListener {
void onResize();
}
private OnResizeListener onResizeListener;
public void setOnResizeListener(OnResizeListener onResizeListener) {
this.onResizeListener = onResizeListener;
}
@Override
public boolean dispatchKeyEventPreIme(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
if (onResizeListener != null) {
onResizeListener.onResize();
}
return true;
}
return super.dispatchKeyEventPreIme(event);
}
}
OnGlobalLayoutListener
视图树中布局发生改变的监听,此方法是可以监听到第一次点击返回键时,软键盘关闭的时机,也可以监听到点击软键盘上的“v”隐藏软键盘按键的时机
参考链接:https://blog.csdn.net/u011181222/article/details/52043001
bottom_layout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
//获取当前窗口可视区域大小
final Rect rect = new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
int visibleHeight = rect.height();
if (rootViewVisibleHeight == 0) {
rootViewVisibleHeight = visibleHeight;
return;
}
//根视图显示高度没有变化,可以看作软键盘显示/隐藏状态没有改变
if (rootViewVisibleHeight == visibleHeight) {
return;
}
//根视图显示高度变小超过200,可以看作软键盘显示了
if (rootViewVisibleHeight - visibleHeight > 200) {
//监听软键盘弹出的一些操作
// ......
rootViewVisibleHeight = visibleHeight;
return;
}
//根视图显示高度变大超过200,可以看作软键盘隐藏了
if (visibleHeight - rootViewVisibleHeight > 200) {
//监听软键盘隐藏的一些操作
// ......
rootViewVisibleHeight = visibleHeight;
return;
}
}
});
一些其它的问题记录:
- 调用edittext的setText方法 软键盘输入方式改变 (当设置软键盘为数字输入时,调用setText方法,软键盘的输入方式会变成英文输入,手动切换到数字输入后,再输入一个数字又会自动切回到英文输入)
参考自:https://stackoverflow.com/questions/26365808/edittext-settext-changes-the-keyboard-type-to-default-from-123-to-abc
解决办法:
将editText.setText(text);
改为editText.getText().clear(); editText.append(text);