场景1
问题描述
常规的,当点击EditText输入框时,软键盘弹出,但键盘会遮挡EditText显示。
解决方案
AndroidManifest文件中,Activity新增配置android:windowSoftInputMode,设置值为adjustPan或adjustResize,如下:
android:name="xxx" android:windowSoftInputMode="adjustPan" /> adjustPan和 adjustResize的区别 adjustPan配置该参数,整个界面会向上平移,显示输入框,但不改变界面的布局。adjustResize配置该参数,系统会重新计算除去软键盘后的界面尺寸,**用更少的界面区域显示内容,**输入框也在其中。 场景2 问题描述 混合开发中,应用在非全屏模式下,WebView加载网页,点击输入框,软键盘遮挡问题。 解决方案 操作方法同上,但是只支持设置值为adjustResize,设置 adjustPan无效。 场景3 问题描述 混合开发中,应用在全屏模式下(Application或activity使用Fullscreen主题、沉浸式状态栏、Immersive Mode等),WebView加载网页,点击输入框,软键盘遮挡问题。android:windowSoftInputMode设置值为adjustPan或adjustResize均无效。这是系统级别的一个坑。 解决方案 方案1 当一个Activity中包含WebView控件时,尽量避免使用全景模式。(当然这个方法治标不治本) 方案2 stackflow上有个大牛提供了解决方案。(stackflow地址) 具体代码如下, import android.app.Activity; import android.graphics.Rect; import android.os.Build; import android.view.View; import android.view.ViewTreeObserver; import android.widget.FrameLayout; /** * 修复WebView全屏模式下,软键盘遮挡问题 */ public final class AndroidBug5497Workaround { private View mChildOfContent; private int usableHeightPrevious; private FrameLayout.LayoutParams frameLayoutParams; private int contentHeight; private boolean isFirst = true; private int statusBarHeight; public static void assistActivity(Activity activity) { new AndroidBug5497Workaround(activity); } private AndroidBug5497Workaround(Activity activity) { //获取状态栏的高度 int resourceId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android"); statusBarHeight = activity.getResources().getDimensionPixelSize(resourceId); FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content); mChildOfContent = content.getChildAt(0); //界面出现变动都会调用这个监听事件 mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { public void onGlobalLayout() { if (isFirst) { contentHeight = mChildOfContent.getHeight();//兼容华为等机型 isFirst = false; } possiblyResizeChildOfContent(); } }); frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams(); } /** * 重新调整布局的高度 */ private void possiblyResizeChildOfContent() { int usableHeightNow = computeUsableHeight(); //当前可见高度和上一次可见高度不一致 布局变动 if (usableHeightNow != usableHeightPrevious) { int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight(); int heightDifference = usableHeightSansKeyboard - usableHeightNow; if (heightDifference > (usableHeightSansKeyboard / 4)) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { frameLayoutParams.height = usableHeightSansKeyboard - heightDifference + statusBarHeight; } else { frameLayoutParams.height = usableHeightSansKeyboard - heightDifference; } } else { frameLayoutParams.height = contentHeight; } mChildOfContent.requestLayout(); usableHeightPrevious = usableHeightNow; } } /** * 计算mChildOfContent可见高度 * * @return */ private int computeUsableHeight() { Rect r = new Rect(); mChildOfContent.getWindowVisibleDisplayFrame(r); return (r.bottom - r.top); } } 将该类新增到项目中,并在对应Activity的onCreate()方法中调用即可。 AndroidBug5497Workaround.assistActivity(this); AndroidBug5497Workaround类解析: 通过findViewById(android.R.id.content)获取Activity界面开发者可控区域的根View。(全屏模式下,即为全部屏幕区域,非全屏模式下为除状态栏外区域) mChildOfContent = content.getChildAt(0); ,获取 Activity 布局的 View (即通过 setContentView() 设置的 View )。 View.getViewTreeObserver()获取一个专门监听当前View树变化的观察者对象。 由于软键盘的弹出,会使View树的全局布局(GlobalLayout)发生变化,所以给当前View树变化的观察者对象绑定监听addOnGlobalLayoutListener。 一旦触发addOnGlobalLayoutListener监听,主要则是调用possiblyResizeChildOfContent()方法,重置界面变化后可用区域。 possiblyResizeChildOfContent()方法中,heightDifference > (usableHeightSansKeyboard / 4)这个判断只有界面的高度变化超过1/4,才重置高度,确保响应软键盘的弹出,排除其他界面变化情况, computeUsableHeight()则是计算除去键盘后重新调整布局的可用高度。 软键盘遮挡界面问题总结 Android输入框软键盘遮挡问题,通常有以下三种情况: 在无WebView的界面下: 按需求配置android:windowSoftInputMode,为adjustPan或adjustResize。 有WebView的界面下: 非全屏模式: 配置android:windowSoftInputMode为adjustResize。 全屏模式: 项目新增一个AndroidBug5497Workaround类,完美解决。 参考文章 精彩文章
发表评论