完美解决android软键盘监听
2016-07-04 11:06
393 查看
最近在做应用性能调优,发现在一个包含有输入框的Activity中,当软键盘弹出的时候,如果直接finish掉此Activity,那么在返回到上一个Activity时,界面的渲染会由于软键盘没有及时的收起而出现卡顿的情况。
很不友好。
于是,本着geek的精神,做就做到极致,就尝试着对这一块做优化。
借助网上一些知识的分享,同时结合自己的理解,最终应用到项目中。
直接上代码。。
首先,在manifest文件中声明此Activity的windowSoftInputMode属性,
android:windowSoftInputMode="stateVisible|adjustResize"
在Activity中 声明所需用到的变量以及布局的事件监听,
然后在onCreat方法中去注册事件监听
mSearchLayout.getViewTreeObserver().addOnGlobalLayoutListener(mOnGlobalLayoutListener);
注意:这个mSearchlayout是你整个Activity的布局引用
最后,别忘了,在onDestroy方法中回收掉事件的监听
到这里,android软键盘的监听就结束了。
**什么?你说全屏的时候,没有效果???**
好吧,我也遇到了。。。
我在项目中实现了所有界面的沉浸式效果,本以为Activity设置了adjustResize,OnGlobalLayoutListener仍然能监听软键盘的变化,结果却是屡试不行。。。
无奈,只能求助。查了一些资料,发现这原来是android的一个bug。下面是具体的bug修复代码片段
把这个类作为一个工具类,添加到项目中,然后,在需要做优化的Activity的onCreate方法中注册activity即可,如:
AndroidAdjustResizeBugFix.assistActivity(this);
以上,就是关于监听软键盘弹出和收起的所有内容。
很不友好。
于是,本着geek的精神,做就做到极致,就尝试着对这一块做优化。
借助网上一些知识的分享,同时结合自己的理解,最终应用到项目中。
直接上代码。。
首先,在manifest文件中声明此Activity的windowSoftInputMode属性,
android:windowSoftInputMode="stateVisible|adjustResize"
在Activity中 声明所需用到的变量以及布局的事件监听,
private boolean mBackEnable = false; private boolean mIsBtnBack = false; private int rootBottom = Integer.MIN_VALUE; private OnGlobalLayoutListener mOnGlobalLayoutListener = new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { Rect r = new Rect(); mSearchLayout.getGlobalVisibleRect(r); // 进入Activity时会布局,第一次调用onGlobalLayout,先记录开始软键盘没有弹出时底部的位置 if (rootBottom == Integer.MIN_VALUE) { rootBottom = r.bottom; return; } // adjustResize,软键盘弹出后高度会变小 if (r.bottom < rootBottom) { mBackEnable = false; } else { mBackEnable = true; if (mIsBtnBack) { finish(); } } } };
然后在onCreat方法中去注册事件监听
mSearchLayout.getViewTreeObserver().addOnGlobalLayoutListener(mOnGlobalLayoutListener);
注意:这个mSearchlayout是你整个Activity的布局引用
最后,别忘了,在onDestroy方法中回收掉事件的监听
@TargetApi(Build.VERSION_CODES.JELLY_BEAN) @Override protected void onDestroy() { if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) { mSearchLayout.getViewTreeObserver().removeGlobalOnLayoutListener(mOnGlobalLayoutListener); } else { mSearchLayout.getViewTreeObserver().removeOnGlobalLayoutListener(mOnGlobalLayoutListener); } super.onDestroy(); }
到这里,android软键盘的监听就结束了。
**什么?你说全屏的时候,没有效果???**
好吧,我也遇到了。。。
我在项目中实现了所有界面的沉浸式效果,本以为Activity设置了adjustResize,OnGlobalLayoutListener仍然能监听软键盘的变化,结果却是屡试不行。。。
无奈,只能求助。查了一些资料,发现这原来是android的一个bug。下面是具体的bug修复代码片段
public class AndroidAdjustResizeBugFix { private View mChildOfContent; private int usableHeightPrevious; private int statusBarHeight; private FrameLayout.LayoutParams frameLayoutParams; private Activity mActivity; private AndroidAdjustResizeBugFix(Activity activity) { mActivity = activity; FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content); mChildOfContent = content.getChildAt(0); statusBarHeight = getStatusBarHeight(); mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { public void onGlobalLayout() { possiblyResizeChildOfContent(); } }); frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams(); } public static void assistActivity(Activity activity) { new AndroidAdjustResizeBugFix(activity); } private void possiblyResizeChildOfContent() { int usableHeightNow = computeUsableHeight(); if (usableHeightNow != usableHeightPrevious) { int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight(); int heightDifference = usableHeightSansKeyboard - usableHeightNow; if (heightDifference > (usableHeightSansKeyboard / 4)) { // keyboard probably just became visible // 如果有高度变化,mChildOfContent.requestLayout()之后界面才会重新测量 // 这里就随便让原来的高度减去了1 frameLayoutParams.height = usableHeightSansKeyboard - 1; } else { // keyboard probably just became hidden frameLayoutParams.height = usableHeightSansKeyboard; } mChildOfContent.requestLayout(); usableHeightPrevious = usableHeightNow; } } private int computeUsableHeight() { Rect r = new Rect(); mChildOfContent.getWindowVisibleDisplayFrame(r); return r.bottom - r.top + statusBarHeight; } private int getStatusBarHeight() { try { Class<?> c = Class.forName("com.android.internal.R$dimen"); Object obj = c.newInstance(); Field field = c.getField("status_bar_height"); int x = Integer.parseInt(field.get(obj).toString()); int dimensionPixelSize = mActivity.getResources().getDimensionPixelSize(x); return dimensionPixelSize; } catch (Exception e) { e.printStackTrace(); } return 0; } }
把这个类作为一个工具类,添加到项目中,然后,在需要做优化的Activity的onCreate方法中注册activity即可,如:
AndroidAdjustResizeBugFix.assistActivity(this);
以上,就是关于监听软键盘弹出和收起的所有内容。
相关文章推荐
- 第一次使用Android Studio时你应该知道的一切配置
- 第一次使用Android Studio时你应该知道的一切配置(二):新建一个属于自己的工程并安装Genymotio...
- Android VideoView 全屏
- Android之补间动画
- android自动弹出软键盘(输入法)
- AndroidRuntime: java.lang.NullPointerExcom.easemob.analytics.EMActiveCollector$1.run(Unknown Source)
- android 画图之setXfermode 处理两图相交叉的情况
- Android Tab -- 使用TabWidget、TabHost、TabActivity来实现
- Android 设计模式 笔记 - 面向对象的六大原则
- Android获取 SIM 卡序列号+读取系统联系人
- android安全退出应用
- Android 沉浸式状态栏攻略 让你的状态栏变色吧
- fir.im Weekly - 聊聊让人向往的远程开发工作
- Android wakelock学习
- Android之逐帧动画
- Android 的开源电话/通讯/IM聊天项目全集
- Android ListView 实现单条刷新
- Android Studio 低版本Gradle升级到高版本时常见问题
- Android n multi-window多窗口支持
- Android --Vibrator--震动服务