zoukankan      html  css  js  c++  java
  • 完美解决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); 

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

  • 相关阅读:
    Ubuntu 16 安装ElasticSearch
    二叉树
    归并排序
    快速排序
    Git、Github使用
    445. 两数相加 II
    141. 环形链表
    92. 反转链表 II
    19. 删除链表的倒数第N个节点
    2. 两数相加
  • 原文地址:https://www.cnblogs.com/shelly-li/p/5639833.html
Copyright © 2011-2022 走看看