美文网首页
Cordova&ionic android 状态栏和底部导航栏适

Cordova&ionic android 状态栏和底部导航栏适

作者: 一只特立独行的道哥 | 来源:发表于2020-11-23 18:05 被阅读0次

    在APP使用过程中(尤其是在华为、vivo等国产手机上),会出现以下适配问题:

    1. 底部导航栏遮挡住footerBar或其他内容
    2. 状态栏遮挡住header等内容
    3. 初始化时正常,弹出键盘或从后台再切换回来时再次出现1问题并不可还原
    4. 彻底隐藏底部导航栏时,部分手机无法唤起底部导航栏,又不支持上滑或左滑来切出,从而导致无法退出APP

    解决方案

    网上很多博客建议使用fitsystemwindows,如这篇博客,但是因为当前APP是cordova项目,不能轻易更改cordova的webView初始化代码,此方案无效,即使实现也会有漏网之鱼。最终解决方案是在布局变化时(后台切回、键盘弹出收起等)重新计算页面高度,动态更新。从而解决问题。

    参考资料: 参考资料

    实施步骤

    1. 重写StatusBar.java 的run方法,改后如下

     public void initialize(final CordovaInterface cordova, CordovaWebView webView) {
            LOG.v(TAG, "StatusBar: initialization");
            super.initialize(cordova, webView);
    
            this.cordova.getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Window window = cordova.getActivity().getWindow();
                    window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
                    window.setStatusBarColor(Color.TRANSPARENT);
                    //添加内容end
                    window.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
    
                }
            });
        }
    

    2. 将config.xml中的resizeOnFullScreen设置为false

    此举是为了避免keyboard插件又重新计算一次,导致出错

    3. 动态计算代码: FixScreen.java

      package com.tehang.TMC;
    
    import android.content.Context;
    import android.content.res.Resources;
    import android.graphics.Rect;
    import android.util.Log;
    import android.view.View;
    import android.view.ViewGroup;
    import android.view.ViewTreeObserver;
    
    import java.lang.reflect.Method;
    
    public class FixScreen {
        public static void assistActivity(View content) {
            new FixScreen(content);
        }
        private View mChildOfContent;
        private int usableHeightPrevious;
        private ViewGroup.LayoutParams frameLayoutParams;
        private FixScreen(View content) {
            mChildOfContent = content;
            mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                public void onGlobalLayout() {
                    possiblyResizeChildOfContent();
                }
            });
            frameLayoutParams = mChildOfContent.getLayoutParams();
        }
        private void possiblyResizeChildOfContent() {
            int usableHeightNow = computeUsableHeight();
            Log.d("usableHeightNow", "possiblyResizeChildOfContent() returned: " + usableHeightNow);
            if (usableHeightNow != usableHeightPrevious) {
                frameLayoutParams.height = usableHeightNow;
                mChildOfContent.requestLayout();
                usableHeightPrevious = usableHeightNow;
            }
        }
    
        private int computeUsableHeight() {
            Rect r = new Rect();
            mChildOfContent.getWindowVisibleDisplayFrame(r);
            return (r.bottom);
        }
        public static boolean checkDeviceHasNavigationBar(Context context) {
            boolean hasNavigationBar = false;
            Resources rs = context.getResources();
            int id = rs.getIdentifier("config_showNavigationBar", "bool", "android");
            if (id > 0) {
                hasNavigationBar = rs.getBoolean(id);
            }
            try {
                Class systemPropertiesClass = Class.forName("android.os.SystemProperties");
                Method m = systemPropertiesClass.getMethod("get", String.class);
                String navBarOverride = (String) m.invoke(systemPropertiesClass, "qemu.hw.mainkeys");
                if ("1".equals(navBarOverride)) {
                    hasNavigationBar = false;
                } else if ("0".equals(navBarOverride)) {
                    hasNavigationBar = true;
                }
            } catch (Exception e) {
            }
            return hasNavigationBar;
        }
    }
    
    

    4. 在MainActivity.java中调用FixScreen,代码如下:

     @Override
        public void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            Bundle extras = getIntent().getExtras();
            if (extras != null && extras.getBoolean("cdvStartInBackground", false)) {
                moveTaskToBack(true);
            }
            loadUrl(launchUrl);
            fixScreenOverlap();
            removeInviteTokenData();
        }
    
        /** 修复导航栏和状态栏引起的遮挡问题 */
        private void fixScreenOverlap(){
            if (FixScreen.checkDeviceHasNavigationBar(this)) {
                FixScreen.assistActivity(findViewById(android.R.id.content));
            }
        }
    

    相关文章

      网友评论

          本文标题:Cordova&ionic android 状态栏和底部导航栏适

          本文链接:https://www.haomeiwen.com/subject/qlpviktx.html