当前位置:   article > 正文

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

webview键盘遮挡输入框

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

我遇到的这个问题,花费了好几天时间去解决,后面才发现该问题可能很早以前就存在了,而且很多人特意将其解决方式以 5497-bug 命名… 不过还是有必要说一下我所遇问题和解决过程

所遇问题

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

解决过程

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

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

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

解决方案

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

Tip:看实现的时候发现主要用到了 WindowManager().getDefaultDisplay() ,从 Display()来看应该是一个显示类,还用了 DisplayMetricsgetRealMetricsgetMetrics ,给大家分享下这几个API的意义

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

  • d.getMetrics() - 去除状态栏和导航栏的总高度

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

    • 这个方法同样用于填充提供的 DisplayMetrics 对象,但它获取的是实际的屏幕度量信息
    • getMetrics() 不同,getRealMetrics() 返回的屏幕尺寸包括了系统装饰元素所占用的空间,即它提供了整个物理屏幕的尺寸

简单来说getMetrics() 提供的是应用可用的屏幕区域的度量信息,而 getRealMetrics() 提供的是整个物理屏幕的度量信息,包括系统 UI 元素所占用的部分

  1. copy 下方 AndroidBug5497Workaround 到项目中
package cn.com.xx;

import android.app.Activity;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;

public class AndroidBug5497Workaround {
    // 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.
    private Activity mActivity;

    public static void assistActivity(Activity activity) {
        new AndroidBug5497Workaround(activity);
    }

    private View mChildOfContent;
    private int usableHeightPrevious;
    private FrameLayout.LayoutParams frameLayoutParams;

    private AndroidBug5497Workaround(Activity activity) {
        this.mActivity = activity;
        FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);
        mChildOfContent = content.getChildAt(0);
        mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            public void onGlobalLayout() {
                possiblyResizeChildOfContent();
            }
        });
        frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();
    }

    private void possiblyResizeChildOfContent() {
        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;
        }
    }

    private int computeUsableHeight() {
        Rect r = new Rect();
        mChildOfContent.getWindowVisibleDisplayFrame(r);
        return (r.bottom - r.top);// 全屏模式下: return r.bottom
    }

    public static boolean isHaveSoftKey(Activity activity) {
        Display d = activity.getWindowManager().getDefaultDisplay();
        DisplayMetrics realDisplayMetrics = new DisplayMetrics();
        d.getRealMetrics(realDisplayMetrics);
        int realHeight = realDisplayMetrics.heightPixels;
        int realWidth = realDisplayMetrics.widthPixels;
        DisplayMetrics displayMetrics = new DisplayMetrics();
        d.getMetrics(displayMetrics);
        int displayHeight = displayMetrics.heightPixels;
        int displayWidth = displayMetrics.widthPixels;
        return (realWidth - displayWidth) > 0 || (realHeight - displayHeight) > 0;
    }

    public static int getBottomSoftKeysHeight(Activity activity) {
        Display d = activity.getWindowManager().getDefaultDisplay();

        DisplayMetrics realDisplayMetrics = new DisplayMetrics();
        d.getRealMetrics(realDisplayMetrics);
        int realHeight = realDisplayMetrics.heightPixels;

        DisplayMetrics displayMetrics = new DisplayMetrics();
        d.getMetrics(displayMetrics);
        int displayHeight = displayMetrics.heightPixels;
        return (realHeight - displayHeight);
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  1. 在对应ActivityFragment组件的 onCreate() 周期内加入 AndroidBug5497Workaround.assistActivity(this)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_layout)
        AndroidBug5497Workaround.assistActivity(this)
    }
  • 1
  • 2
  • 3
  • 4
  • 5
声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号