完美解决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);

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

原创不容易,希望大家多多支持!如需转载,请标明出处! http://www.cnblogs.com/shelly-li/

时间: 2024-10-13 05:17:48

完美解决android软键盘监听的相关文章

完美解决android软键盘监听1

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

Android之键盘监听的运行机理【看清键盘监听的本质】【入门版】

以EditText为例: 1.Activity本身也有按键监听 editText按键监听与Activity按键监听关系: Activity本身也有按键监听 而且分按下和松开两个事件监听 editText按键监听不分按下,和松开,准确的说:它把这两个事件放在了一个监听事件里了 return false ,editText按键监听事件执行完之后,会向下传第,即接着执行Activity的按键监听 return true :终止向下传递,不会执行Activity的按键监听 2.软键盘不能响应按键监听(只

解决 Android 软键盘挡住输入框的问题

当在Android的layout设计里面如果输入框过多,则在输入弹出软键盘的时候,下面的输入框会有一部分被软件盘挡住,从而不能获取焦点输入. 下面提供三种解决办法:    方法一:在你的activity中的对应的java文件中oncreate中setContentView之前写上这个代码getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); 该方法是最简单的    方法二:在 项目的Andro

解决Android软键盘弹出引起的各种不适

在做输入信息页面的时候,经常会遇到键盘挡住输入框或者将一些控件顶起的情况,android为此提供了一系列的的配置参数供选择,可以在androidmanufist.xml的对应Activity的windowSoftInputMode属性中进行配置: 详细说明这四个参数: int SOFT_INPUT_ADJUST_NOTHING Adjustment option for softInputMode: set to have a window not adjust for a shown inpu

安卓软键盘监听

转:https://gist.github.com/felHR85/6070f643d25f5a0b3674 SoftKeyboard.java /* * Author: Felipe Herranz ([email protected]) * Contributors:Francesco Verheye ([email protected]) * Israel Dominguez ([email protected]) */ import java.util.ArrayList; import

关于android软键盘enter键的替换与事件监听

android软键盘事件监听enter键 软件盘的界面替换只有一个属性android:imeOptions,这个属性的可以取的值有 normal,actionUnspecified,actionNone,actionGo,actionSearch,actionSend,actionNext,actionDone, 例如当值为actionNext时enter键外观变成一个向下箭头,而值为actionDone时enter键外观则变成了“完成”两个字. 我们也可以重写enter的事件,方法如下 Jav

Android软键盘弹出时把布局顶上去的解决方法

原文: 解决Andriod软键盘出现把原来的布局给顶上去的方法(转) 链接:http://blog.sina.com.cn/s/blog_9564cb6e0101g2eb.html 决方法,在mainfest.xml中,对那个Activity加: <activityandroid:name=".activity.HomeActivity"android:windowSoftInputMode="adjustPan|stateHidden"></ac

Android软键盘隐藏,遮挡EidtText解决办法

一.自动弹出软键盘 Timer timer=new Timer(); timer.schedule(new TimerTask() { public void run() { InputMethodManager inputMethodManager=(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); inputMethodManager.toggleSoftInput(0, InputMethodManage

Android之如何设置键盘监听

5.设置键盘监听[以EditText为例] username.setOnKeyListener(new OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { // TODO Auto-generated method stub switch (keyCode) { case KeyEvent.KEYCODE_1: Toast.makeText(MainActivity.thi