完美解决android软键盘监听

Posted ADark0915

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了完美解决android软键盘监听相关的知识,希望对你有一定的参考价值。

最近在做应用性能调优,发现在一个包含有输入框的Activity中,当软键盘弹出的时候,如果直接finish掉此Activity,那么在返回到上一个Activity时,界面的渲染会由于软键盘没有及时的收起而出现卡顿的情况。
很不友好。
于是,本着geek的精神,做就做到极致,就尝试着对这一块做优化。
借助网上一些知识的分享,同时结合自己的理解,最终应用到项目中。
直接上代码。。
首先,在manifest文件中声明此Activity的windowSoftInputMode属性,

 1 android:windowSoftInputMode="stateVisible|adjustResize" 

在Activity中 声明所需用到的变量以及布局的事件监听,

 1 private boolean mBackEnable = false;
 2     private boolean mIsBtnBack = false;
 3     private int rootBottom = Integer.MIN_VALUE;
 4     private OnGlobalLayoutListener mOnGlobalLayoutListener = new OnGlobalLayoutListener() {
 5         @Override
 6         public void onGlobalLayout() {
 7             Rect r = new Rect();
 8             mSearchLayout.getGlobalVisibleRect(r);
 9             // 进入Activity时会布局,第一次调用onGlobalLayout,先记录开始软键盘没有弹出时底部的位置
10             if (rootBottom == Integer.MIN_VALUE) {
11                 rootBottom = r.bottom;
12                 return;
13             }
14             // adjustResize,软键盘弹出后高度会变小
15             if (r.bottom < rootBottom) {
16                 mBackEnable = false;
17             } else {
18                 mBackEnable = true;
19                 if (mIsBtnBack) {
20                     finish();
21                 }
22             }
23         }
24     };

然后在onCreat方法中去注册事件监听

 1 mSearchLayout.getViewTreeObserver().addOnGlobalLayoutListener(mOnGlobalLayoutListener); 

注意:这个mSearchlayout是你整个Activity的布局引用

最后,别忘了,在onDestroy方法中回收掉事件的监听

 1 @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
 2     @Override
 3     protected void onDestroy() {
 4         if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) {
 5             mSearchLayout.getViewTreeObserver().removeGlobalOnLayoutListener(mOnGlobalLayoutListener);
 6         } else {
 7             mSearchLayout.getViewTreeObserver().removeOnGlobalLayoutListener(mOnGlobalLayoutListener);
 8         }
 9         super.onDestroy();
10     }

到这里,android软键盘的监听就结束了。

**什么?你说全屏的时候,没有效果???**

好吧,我也遇到了。。。

我在项目中实现了所有界面的沉浸式效果,本以为Activity设置了adjustResize,OnGlobalLayoutListener仍然能监听软键盘的变化,结果却是屡试不行。。。

无奈,只能求助。查了一些资料,发现这原来是android的一个bug。下面是具体的bug修复代码片段

 1 public class AndroidAdjustResizeBugFix {
 2     private View mChildOfContent;
 3     private int usableHeightPrevious;
 4     private int statusBarHeight;
 5     private FrameLayout.LayoutParams frameLayoutParams;
 6     private Activity mActivity;
 7 
 8     private AndroidAdjustResizeBugFix(Activity activity) {
 9         mActivity = activity;
10         FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);
11         mChildOfContent = content.getChildAt(0);
12         statusBarHeight = getStatusBarHeight();
13         mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
14             public void onGlobalLayout() {
15                 possiblyResizeChildOfContent();
16             }
17         });
18         frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();
19     }
20     public static void assistActivity(Activity activity) {
21         new AndroidAdjustResizeBugFix(activity);
22     }
23     private void possiblyResizeChildOfContent() {
24         int usableHeightNow = computeUsableHeight();
25         if (usableHeightNow != usableHeightPrevious) {
26             int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
27             int heightDifference = usableHeightSansKeyboard - usableHeightNow;
28             if (heightDifference > (usableHeightSansKeyboard / 4)) {
29                 // keyboard probably just became visible
30                 // 如果有高度变化,mChildOfContent.requestLayout()之后界面才会重新测量
31                 // 这里就随便让原来的高度减去了1
32                 frameLayoutParams.height = usableHeightSansKeyboard - 1;
33             } else {
34                 // keyboard probably just became hidden
35                 frameLayoutParams.height = usableHeightSansKeyboard;
36             }
37             mChildOfContent.requestLayout();
38             usableHeightPrevious = usableHeightNow;
39         }
40     }
41     private int computeUsableHeight() {
42         Rect r = new Rect();
43         mChildOfContent.getWindowVisibleDisplayFrame(r);
44         return r.bottom - r.top + statusBarHeight;
45     }
46     private int getStatusBarHeight() {
47         try {
48             Class<?> c = Class.forName("com.android.internal.R$dimen");
49             Object obj = c.newInstance();
50             Field field = c.getField("status_bar_height");
51             int x = Integer.parseInt(field.get(obj).toString());
52             int dimensionPixelSize = mActivity.getResources().getDimensionPixelSize(x);
53             return dimensionPixelSize;
54         } catch (Exception e) {
55             e.printStackTrace();
56         }
57         return 0;
58     }
59 }


把这个类作为一个工具类,添加到项目中,然后,在需要做优化的Activity的onCreate方法中注册activity即可,如:

1 AndroidAdjustResizeBugFix.assistActivity(this); 

以上,就是关于监听软键盘弹出和收起的所有内容。

 

以上是关于完美解决android软键盘监听的主要内容,如果未能解决你的问题,请参考以下文章

android设置软键盘搜索键以及监听搜索键点击时发生两次事件的问题解决

android设置软键盘搜索键以及监听搜索键点击时发生两次事件的问题解决

Android 监听软键盘的高度并解决其覆盖输入框的问题

Android 监听软键盘的高度并解决其覆盖输入框的问题

Android 监听软键盘的高度并解决其覆盖输入框的问题

对Android 软键盘向下的监听