Android软键盘弹出时如何处理页面布局

Android开发时经常会用到软键盘,当软键盘弹出顶起当前布局是常见的问题。 如何解决软件盘导致的页面布局被打乱的问题呢? 先了解下软键盘和 Activity 的几个交互模式(windowSoftInputMode): 1,stateUnspecified:软键盘的状态并没有指定,系统将选择一个合适的状态或依赖于主题的设置 2,stateUnchanged:当这个activity出现时,软键盘将一直保持在上一个activity里的状态,无论是隐藏还是显示 3,stateHidden:用户选择activity时,软键盘总是被隐藏 4,stateAlwaysHidden:当该Activity主窗口获取焦点时,软键盘也总是被隐藏的 5,stateVisible:软键盘通常是可见的 6,stateAlwaysVisible:用户选择activity时,软键盘总是显示的状态 7,adjustUnspecified:默认设置,通常由系统自行决定是隐藏还是显示。使用该设置,软键盘弹出,页面里的图片可能会有影响。 8,adjustResize:该Activity总是调整屏幕的大小以便留出软键盘的空间 9,adjustPan:当前窗口的内容将自动移动以便当前焦点从不被键盘覆盖和用户能总是看到输入内容的部分 了解这些交互模式后,百度一下网上常见的解决方案有两种。 方案1: 将 windowSoftInputMode 属性设置为 adjustResize|stateHidden: ``` android:windowSoftInputMode="adjustResize|stateHidden" ``` 方案2: 将 windowSoftInputMode 属性设置为 adjustPan|stateHidden: ``` android:windowSoftInputMode="adjustPan|stateHidden" ``` 在一般场景这两种方案可以解决问题,但是当页面结构复杂层次比较多时,使用这两种方案软键盘还是会破环当前页面布局,或者遮挡住输入框。 这里提供一种方案,从 AndroidManifest.xml 配置文件和代码两方面入手来解决软件盘破坏页面布局的问题。 该方案以一个包含10+个 EditeText 的页面为例,所有 EditText 通过代码动态添加。 步骤1:设置 AndroidManifest.xml 里的 windowSoftInputMode 为 adjustResize|stateHidden ``` <activity android:name=".view.PostActivity" android:configChanges="keyboardHidden" android:windowSoftInputMode="adjustResize|stateHidden" /> ``` 步骤2:软键盘监听 ``` public class KeyboardListener { final String TAG=this.getClass().getName(); private View rootView; // activity的根视图 int rootViewVisibleHeight; // 记录根视图显示的高度 private OnKeyBoardDisplayListener onKeyBoardDisplayListener; public KeyboardListener(Activity activity){ // 获取activity的根视图 rootView = activity.getWindow().getDecorView(); // 监听视图树中全局布局发生改变或者视图树中某个视图的可视状态发生改变 rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { // 获取当前根视图在屏幕上显示的大小 Rect rect = new Rect(); rootView.getWindowVisibleDisplayFrame(rect); int visibleHeight = rect.height(); if(rootViewVisibleHeight == 0){ rootViewVisibleHeight = visibleHeight; return; } //根视图显示高度没有变化,可以看做软键盘显示/隐藏状态没有变化 if(rootViewVisibleHeight == visibleHeight){ return; } // 根视图显示高度变小超过200,可以看做软键盘显示了 if(rootViewVisibleHeight -visibleHeight > 200){ if(onKeyBoardDisplayListener !=null){ onKeyBoardDisplayListener.keyBoardShow(rootViewVisibleHeight - visibleHeight); } rootViewVisibleHeight = visibleHeight; return; } // 根视图显示高度变大超过了200,可以看做软键盘隐藏了 if(visibleHeight - rootViewVisibleHeight > 200){ if(onKeyBoardDisplayListener != null){ onKeyBoardDisplayListener.keyBoardHide(visibleHeight - rootViewVisibleHeight); } rootViewVisibleHeight = visibleHeight; return; } } }); } public interface OnKeyBoardDisplayListener{ void keyBoardShow(int height); void keyBoardHide(int height); } public void setOnSoftKeyBoardChangeListener(OnKeyBoardDisplayListener onKeyBoardDisplayListener) { this.onKeyBoardDisplayListener = onKeyBoardDisplayListener; } } ``` 步骤3:Activity 里添加对软键盘的监听 ``` KeyboardListener softKeyboardListener = new KeyboardListener(this); softKeyboardListener.setOnSoftKeyBoardChangeListener(new KeyboardListener.OnKeyBoardDisplayListener() { @Override public void keyBoardShow(final int height) {           /**低版本的 android:windowSoftInputMode="adjustResize" 无法生效,软键盘弹出时布局会被破坏。直接返回即可**/          if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M){          return;          } /**获取当前点击的控件**/ View view=getWindow().getDecorView().findFocus();/**获取坐标。location[0] 为 x,1为y**/ int[] location = new int[2] ; view.getLocationInWindow(location); ScrollView scrollView=getView(R.id.scroll_view);          int scroll_y_distance=height-(ScreenUtil.getScreenHeightPx(PostActivity.this)-location[1]); scrollView.setPadding(0,0,0,scroll_y_distance); scrollView.scrollTo(0,scroll_y_distance); } @Override public void keyBoardHide(int height) { ScrollView scrollView=getView(R.id.scroll_view); scrollView.setPadding(0,0,0,0); } }); ``` 步骤4:配置页面xml文件,所有的内容通过代码追加到 content_container 里 ``` <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" style="@style/Match2"> <ScrollView android:id="@+id/scroll_view" style="@style/Match2" android:scrollbars="none">   <LinearLayout   android:id="@+id/content_container"   style="@style/content_container">   </LinearLayout> </ScrollView> </FrameLayout> ``` 以上4步完成后,软键盘弹出页面会正常展示,弹出的软件盘不会破坏页面布局,不用担心 EditText 被弹出的软键盘遮挡。
我的笔记