开发笔记---软键盘遮挡输入框和导航栏遮挡了内容的解决方案

在解决软键盘挡住输入框的问题的时候,都知道在AndroidManifest.xml为Activity声明

android:windowSoftInputMode="adjustResize"
android:windowSoftInputMode="adjustPan"

adjustResize会按软键盘覆盖后的可见区域大小,传给app重新布局,这样布局就被挤压了。
adjustPan会根据是否有ListView,ScrollView去滚动视图。

问题

有时候你设adjustResize,发现输入框还是被遮挡。软键盘弹起和隐藏的时候,布局中onLayout被调用,但传过来的left,top,left,right值不变,onSizeChange也没被调用,也就是说adjustResize没有起到他实际的作用。

我的例子就是使用全屏沉浸的布局的时候

View decorView = getWindow().getDecorView();
        if (Build.VERSION.SDK_INT >= 21) {
            int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
            decorView.setSystemUiVisibility(option);
            getWindow().setStatusBarColor(Color.TRANSPARENT);
            getWindow().setNavigationBarColor(getResources().getColor(R.color.colorPrimary));
        } 

而且是混合应用,里面是WebView页面,使用HTML5编写。
不知道是不是Web框架的原因,adjustResize无效,导致内容被软键盘遮挡,被华为等手机的导航栏遮挡

解决方案

既然系统做不了,我们就自己来做,搜到一段好用的解决方法

public class ScrollHelper {
    // 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.

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

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

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

    //重新挤压布局
    private void adjustResize() {
        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;
            } else {
                // keyboard probably just became hidden
                frameLayoutParams.height = usableHeightSansKeyboard;
            }

            mChildOfContent.requestLayout();
            usableHeightPrevious = usableHeightNow;
        }
    }

    /**
     * 计算有效高度
     */
    private int computeUsableHeight() {
        Rect r = new Rect();
        mChildOfContent.getWindowVisibleDisplayFrame(r);
        return (r.bottom);
    }
}

这段代码的类名和方法我做了些改变,原理是对android.R.id.content这个View,根据他实际的可见高度重新Resize。

代码解决软键盘遮挡没有问题,在于判断 if (heightDifference > (usableHeightSansKeyboard / 4)) ,需要至少1/4的屏幕高度,才认为是软键盘弹出。

导航栏

导航栏差不多跟软键盘一样的处理方式,但没有1/4屏幕高度,所以只要去掉这个条件,始终用 frameLayoutParams.height = usableHeightSansKeyboard - heightDifference就解决了。。

在Acitivity里面使用

  @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        .
        .
        .
        //软键盘和导航栏遮挡了内容的解决方案
        ScrollHelper.assistActivity(this);
    }

你可能感兴趣的:(android)