React Native笔记(三):解决在RN中使用Android原生WebView时输入框被遮挡问题

如题,在解决该问题前,上网搜了一下资料,找到了下面这个方案:
Android webView输入框软键盘遮挡问题-终极解决方案(不好使你打我)

但是,这在纯原生上可行,在rn上却没有效果。主要原因是rn有自己的一套布局测量绘制机制,导致在原生调用requestLayout()没有响应,经过几次实践,得出下面针对rn的解决办法。

  1. 重写WebView的requestLayout方法,rn绘制时主动通知原生重新布局WebView
public class CusWebView extends WebView{
    
    
    private boolean mLayoutEnqueued;

    public CusWebView(Context context) {
    
    
        super(context);
    }

    public CusWebView(Context context, AttributeSet attrs) {
    
    
        super(context, attrs);
    }

    public CusWebView(Context context, AttributeSet attrs, int defStyleAttr) {
    
    
        super(context, attrs, defStyleAttr);
    }

    public CusWebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    
    
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    public void requestLayout() {
    
    
        super.requestLayout();
        if (isAttachedToWindow() && !mLayoutEnqueued) {
    
    
            mLayoutEnqueued = true;
            ReactChoreographer.getInstance().postFrameCallback(ReactChoreographer.CallbackType.DISPATCH_UI, new ChoreographerCompat.FrameCallback() {
    
    
                @Override
                public void doFrame(long frameTimeNanos) {
    
    
                    mLayoutEnqueued = false;
                    measure(
                            MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.EXACTLY),
                            MeasureSpec.makeMeasureSpec(getLayoutParams().height, MeasureSpec.EXACTLY));
                    layout(getLeft(), getTop(), getRight(), getLayoutParams().height);
                }
            });
        }
    }
}
  1. 修改AndroidBug5497Workaround类
public class AndroidBug5497Workaround {
    
    
    public static void assistActivity(Activity activity) {
    
    
        new AndroidBug5497Workaround(activity);
    }

    private View mChildOfContent;
    private int usableHeightPrevious = -1;
    private ViewGroup.LayoutParams frameLayoutParams;
    Activity mActivity;

    private AndroidBug5497Workaround(Activity activity) {
    
    
        this.mActivity = activity;
        ViewGroup vp = activity.findViewById(android.R.id.content);
        vp.post(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                mChildOfContent = findWebView(vp);
                if (mChildOfContent == null) {
    
    
                    mChildOfContent = vp;
                }

              	mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    
    
                    public void onGlobalLayout() {
    
    
                        possiblyResizeChildOfContent();
                    }
                });
            }
        });
    }

    public View findWebView(ViewGroup vp){
    
    
        for (int i = vp.getChildCount() - 1; i >=0 ; i--){
    
    
            View view = vp.getChildAt(i);
            if (view instanceof CusWebView){
    
    
                return view;
            }else if (view instanceof ViewGroup){
    
    
                View temp = findWebView((ViewGroup) view);
                if (temp != null){
    
    
                    return temp;
                }
            }
        }
        return null;
    }

    private void possiblyResizeChildOfContent() {
    
    
        int visibleHeight = computeUsableHeight();
        if (visibleHeight != usableHeightPrevious) {
    
    
            if (frameLayoutParams == null) {
    
    
                frameLayoutParams = mChildOfContent.getLayoutParams();
            }
            int currentContentHeight = mChildOfContent.getHeight();
            int heightDifference = Math.abs(currentContentHeight - visibleHeight);
            
            frameLayoutParams.height = visibleHeight;
            usableHeightPrevious = visibleHeight;
            mChildOfContent.requestLayout();
        }
    }

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

}

关健是找出上一步重写的WebView对象,调用它的requestLayout方法

猜你喜欢

转载自blog.csdn.net/weixin_40855673/article/details/124444563