0


Android进阶之路 - 解决WebView加载H5时软键盘遮挡输入框问题

经验总是有限的,越学越无知,总是能深刻的了解到学无止境

我遇到的这个问题,花费了好几天时间去解决,后面才发现该问题可能很早以前就存在了,而且很多人特意将其解决方式以

5497-bug

命名… 不过还是有必要说一下我所遇问题和解决过程

所遇问题

  1. 项目中 WebView 加载H5正常显示,但是涉及到输入框交互时会遮挡H5输入框,无法正常顶起输入框
  2. 其他端可正常在弹出键盘时顶起输入框,如IOS、或一些三方应用内

解决过程

  1. WebView 组件换为系统提供的原始组件,未进行任何二次封装(可正常顶起输入框,但其他业务受影响,故放弃)
  2. 将当前二次封装的组件剥离到外部进行测试,模拟输入框场景(无效,依旧无法正常顶起输入框)
  3. 变更对应 WebView 承载 Activity(WebViewActivity)的configChanges属性(无效
<activityandroid:name=".xxx.WebViewActivity"android:configChanges="orientation|screenSize|keyboardHidden"android:exported="false"android:screenOrientation="portrait"android:windowSoftInputMode="stateHidden|adjustResize"/>

换个思想出发,假设在Android中遇到类似问题如何处理?

  • 监听键盘弹出状态,动态在输入框下增删Holder布局(简单)
  • 监听键盘弹出状态,动态设置当前布局高度(需要细心调试)
  • 监听当前布局,查看遮挡范围是否达到设置阈值,然后变更高度,再进行绘制(当前解决方案)

解决方案

这里采用的解决方式就是获取屏幕高度后,通过动态监听被遮挡范围(键盘弹出时会遮挡显示范围),实时改变布局高度

Tip:看实现的时候发现主要用到了

WindowManager().getDefaultDisplay()

,从

Display()

来看应该是一个显示类,还用了

DisplayMetrics

getRealMetrics

getMetrics 

,给大家分享下这几个API的意义

Display d = activity.getWindowManager().getDefaultDisplay();

  • d.getMetrics() - 去除状态栏和导航栏的总高度- 这个方法用于填充提供的 DisplayMetrics 对象,获取当前屏幕的度量信息- 它返回的屏幕尺寸通常不包括系统装饰元素(如状态栏和导航栏)所占用的空间
  • d.getRealMetrics() - 屏幕总高度- 这个方法同样用于填充提供的 DisplayMetrics 对象,但它获取的是实际的屏幕度量信息- 与 getMetrics() 不同,getRealMetrics() 返回的屏幕尺寸包括了系统装饰元素所占用的空间,即它提供了整个物理屏幕的尺寸

简单来说

getMetrics()

提供的是应用可用的屏幕区域的度量信息,而

getRealMetrics()

提供的是整个物理屏幕的度量信息,包括系统 UI 元素所占用的部分

  1. copy 下方 AndroidBug5497Workaround 到项目中
packagecn.com.xx;importandroid.app.Activity;importandroid.graphics.Rect;importandroid.util.DisplayMetrics;importandroid.view.Display;importandroid.view.View;importandroid.view.ViewTreeObserver;importandroid.widget.FrameLayout;publicclassAndroidBug5497Workaround{// For more information, see https://code.google.com/p/android/issues/detail?id=5497// To use this class, simply invoke assistActivity() on an Activity that already has its content view set.privateActivity mActivity;publicstaticvoidassistActivity(Activity activity){newAndroidBug5497Workaround(activity);}privateView mChildOfContent;privateint usableHeightPrevious;privateFrameLayout.LayoutParams frameLayoutParams;privateAndroidBug5497Workaround(Activity activity){this.mActivity = activity;FrameLayout content =(FrameLayout) activity.findViewById(android.R.id.content);
        mChildOfContent = content.getChildAt(0);
        mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(newViewTreeObserver.OnGlobalLayoutListener(){publicvoidonGlobalLayout(){possiblyResizeChildOfContent();}});
        frameLayoutParams =(FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();}privatevoidpossiblyResizeChildOfContent(){int bottomSoftKeysHeight =0;boolean haveSoftKey =isHaveSoftKey(mActivity);if(haveSoftKey){
            bottomSoftKeysHeight =getBottomSoftKeysHeight(mActivity);}int usableHeightNow =computeUsableHeight();if(usableHeightNow != usableHeightPrevious){int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();//屏幕高度int heightDifference = usableHeightSansKeyboard - usableHeightNow;//被遮挡高度if(heightDifference >(usableHeightSansKeyboard /4)){//被遮挡四分之一// keyboard probably just became visible//                frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;//之前的,因顶起太高,改为下方高度,有问题可以调这里
                frameLayoutParams.height = usableHeightSansKeyboard - heightDifference +(bottomSoftKeysHeight /2);}else{// keyboard probably just became hidden//                frameLayoutParams.height = usableHeightSansKeyboard;//之前的,因顶起太高,改为下方高度,有问题可以调这里
                frameLayoutParams.height = usableHeightSansKeyboard -(bottomSoftKeysHeight /2);}
            mChildOfContent.requestLayout();
            usableHeightPrevious = usableHeightNow;}}privateintcomputeUsableHeight(){Rect r =newRect();
        mChildOfContent.getWindowVisibleDisplayFrame(r);return(r.bottom - r.top);// 全屏模式下: return r.bottom}publicstaticbooleanisHaveSoftKey(Activity activity){Display d = activity.getWindowManager().getDefaultDisplay();DisplayMetrics realDisplayMetrics =newDisplayMetrics();
        d.getRealMetrics(realDisplayMetrics);int realHeight = realDisplayMetrics.heightPixels;int realWidth = realDisplayMetrics.widthPixels;DisplayMetrics displayMetrics =newDisplayMetrics();
        d.getMetrics(displayMetrics);int displayHeight = displayMetrics.heightPixels;int displayWidth = displayMetrics.widthPixels;return(realWidth - displayWidth)>0||(realHeight - displayHeight)>0;}publicstaticintgetBottomSoftKeysHeight(Activity activity){Display d = activity.getWindowManager().getDefaultDisplay();DisplayMetrics realDisplayMetrics =newDisplayMetrics();
        d.getRealMetrics(realDisplayMetrics);int realHeight = realDisplayMetrics.heightPixels;DisplayMetrics displayMetrics =newDisplayMetrics();
        d.getMetrics(displayMetrics);int displayHeight = displayMetrics.heightPixels;return(realHeight - displayHeight);}}
  1. 在对应ActivityFragment组件的 onCreate() 周期内加入 AndroidBug5497Workaround.assistActivity(this)
overridefunonCreate(savedInstanceState: Bundle?){super.onCreate(savedInstanceState)setContentView(R.layout.activity_layout)
        AndroidBug5497Workaround.assistActivity(this)}

本文转载自: https://blog.csdn.net/qq_20451879/article/details/140344324
版权归原作者 远方那座山 所有, 如有侵权,请联系我们删除。

“Android进阶之路 - 解决WebView加载H5时软键盘遮挡输入框问题”的评论:

还没有评论