源码地址:https://github.com/HuCanui/KeyboradObserver
最近发现公司的app右下角有个小悬浮窗,这个悬浮窗是在Service里面控制显示隐藏的,当键盘弹窗输入时会影响输入。追求完美的我实在看不下去了,给自己提了个需求键盘弹出时隐藏悬浮窗,键盘退出时继续显示。
来!实现一把。通常做法实在activity里面去获取顶级View,然后设置监听OnGlobalLayoutListener,onGlobalLayout的时候检查下顶级View实际的高度是不是比实际的可见的高度大100dp。默认键盘高度大于100dp。
final View activityRoot = getWindow().getDecorView();
if (activityRoot == null) {
return;
}
ViewTreeObserver.OnGlobalLayoutListener layoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
private final Rect r = new Rect();
private final int visibleThreshold = Math.round(dp2px(activity, 100));
@Override
public void onGlobalLayout() {
activityRoot.getWindowVisibleDisplayFrame(r);
int heightDiff = activityRoot.getRootView().getHeight() - r.height();
//键盘是否弹出
boolean isOpen = heightDiff > visibleThreshold;
if (isOpen == wasOpened) {
// keyboard state has not changed
return;
}
wasOpened = isOpen;
}
};
但。。。是,现在是在Service里面,我ca,怎么拿到当前页面RootView。不好意思,夸张了?,还是有很多办法拿到的,比如:在application里面注册Application.ActivityLifecycleCallbacks,onActivityCreated的把activity缓存起来不就好了,能拿到当前Activity,不就可以拿到当前页面RootView了,然后再去设置OnGlobalLayoutListener监听。
能拿到当前页面RootView了也不顶事啊,在Service里面,我就想有人在实时通知我:嘿!键盘弹出啦!嘿!键盘退出啦。
叮咚,EventBus各位大佬应该用得多了吧,我们在RootView
onGlobalLayout的时候检查键盘是否弹出了,然后再发个事件出来也不是什么难事。
application.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
private boolean wasOpened = false;
private final static int KEYBOARD_VISIBLE_THRESHOLD_DP = 100;
@Override
public void onActivityCreated(final Activity activity, Bundle savedInstanceState) {
try {
final View activityRoot = getActivityRoot(activity);
if (activityRoot == null) {
return;
}
ViewTreeObserver.OnGlobalLayoutListener layoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
private final Rect r = new Rect();
private final int visibleThreshold = Math.round(dp2px(activity, KEYBOARD_VISIBLE_THRESHOLD_DP));
@Override
public void onGlobalLayout() {
activityRoot.getWindowVisibleDisplayFrame(r);
int heightDiff = activityRoot.getRootView().getHeight() - r.height();
boolean isOpen = heightDiff > visibleThreshold;
if (isOpen == wasOpened) {
// keyboard state has not changed
return;
}
wasOpened = isOpen;
//发个事件
EventBus.getDefault().post(new KeyboardVisibleEvent(isOpen));
}
};
activityRoot.getViewTreeObserver().addOnGlobalLayoutListener(layoutListener);
}catch (Exception e){
e.printStackTrace();
}
}
@Override
public void onActivityStarted(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
});
然后我做了点简单的小封装,添加了OnGlobalLayoutListener,remove下总是比较友好的,再增加个手动调用方法判断键盘是否正在展示的方法。使用起来就方便多了。不用到处去设置OnGlobalLayoutListener了。支持在任何类里监听键盘事件。
源码地址:https://github.com/HuCanui/KeyboradObserver
使用: 1、在Application的onCreate的时候
KeyboardVisibilityObserver.getInstance().init(this);
2、EventBus开源库加下
implementation 'org.greenrobot:eventbus:3.1.1'
3、在需要监听键盘的事件的类里面注册/反注册下EventBus
EventBus.getDefault().register(this);
EventBus.getDefault().unregister(this);
4、键盘事件监听下
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(KeyboardVisibleEvent event){
Toast.makeText(this, event.isVisible ? "键盘弹起" : "键盘收起", Toast.LENGTH_SHORT).show();
}