1. 程式人生 > >Android中沈浸式狀態欄的應用

Android中沈浸式狀態欄的應用

ack get 實際應用 back ide real server 主界面 resources

在Android5.0版本後,谷歌公司為Android系統加入了很多新特性,刷新了Android用戶的體驗度。而其中的一個新特性就是沈浸式狀態欄。那麽問題來了,很多非移動端的小夥伴就要問了,什麽是沈浸式狀態欄?傳統的手機狀態欄是呈現出黑色條狀的,有的和手機主界面有很明顯的區別。這樣就在一定程度上犧牲了視覺寬度,界面面積變小。而沈浸式狀態欄將狀態欄的顏色變為透明,並將原有的布局沾滿了手機屏幕,使得狀態欄和手機布局內容融為一體。下面,我們來詳細的說明沈浸式狀態欄在項目中的實際應用。

要在當前的Activity界面實現沈浸式,首先我們要在oncreate方法中寫入如下代碼:

getWindow().requestFeature(Window.FEATURE_NO_TITLE);
Window window 
= getWindow(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); window.setStatusBarColor(Color.TRANSPARENT); window.setNavigationBarColor(Color.TRANSPARENT); }

這樣代碼就可以實現沈浸式狀態。由於沈浸式狀態欄只支持5.0以上手機,所以我們在這裏進行了版本判斷。不過實際操作中,有小夥伴又遇到了新的問題。有些有虛擬按鍵的也被沈浸了,這個就會很郁悶了。我們的構思是布局中有一個黑色的view,在有虛擬按鍵的手機上顯示出來,並且高度與虛擬按鍵一致。具體操作如下。

檢查是否具有虛擬按鍵

public static boolean hasNavBar(Context context) {
        Resources res = context.getResources();
        //這種方式一定要註意寫法要正確,內部應該是通過反射去調用的。
        int resourceId = res.getIdentifier("config_showNavigationBar", "bool", "android");
        if (resourceId != 0) {
            boolean hasNav = res.getBoolean(resourceId);
            // check override flag
            String sNavBarOverride = getNavBarOverride();
            if ("1".equals(sNavBarOverride)) {
                hasNav = false;
            } else if ("0".equals(sNavBarOverride)) {
                hasNav = true;
            }
            return hasNav;
        } else { // fallback
            if (Build.VERSION.SDK_INT >= 14) {
                return !ViewConfiguration.get(context).hasPermanentMenuKey();
            } else {
                return false;
            }
        }
    }

判斷虛擬按鍵欄是否重寫

private static String getNavBarOverride() {
        String sNavBarOverride = null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            try {
                Class c = Class.forName("android.os.SystemProperties");
                Method m = c.getDeclaredMethod("get", String.class);
                m.setAccessible(true);
                sNavBarOverride = (String) m.invoke(null, "qemu.hw.mainkeys");
            } catch (Throwable e) {
            }
        }
        return sNavBarOverride;
    }

獲取虛擬按鍵欄高度

public static int getBottomStatusHeight(Context context) {
        int totalHeight = getDpi(context);

        int contentHeight = getScreenHeight(context);

        return totalHeight - contentHeight;
    }

獲取屏幕高度

 public static int getScreenHeight(Context context) {
        WindowManager wm = (WindowManager) context
                .getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics outMetrics = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(outMetrics);
        return outMetrics.heightPixels;
    }
獲取屏幕原始尺寸高度,包括虛擬功能鍵高度
public static int getDpi(Context context) {
        int dpi = 0;
        WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        Display display = windowManager.getDefaultDisplay();
        DisplayMetrics displayMetrics = new DisplayMetrics();
        @SuppressWarnings("rawtypes")
        Class c;
        try {
            c = Class.forName("android.view.Display");
            @SuppressWarnings("unchecked")
            Method method = c.getMethod("getRealMetrics", DisplayMetrics.class);
            method.invoke(display, displayMetrics);
            dpi = displayMetrics.heightPixels;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return dpi;
    }

代碼中設置布局中View的高度

if (hasNavBar(this)) {
            bottomView.getViewTreeObserver().addOnGlobalLayoutListener(
                    new ViewTreeObserver.OnGlobalLayoutListener() {
                        // 當layout執行結束後回調此方法
                        @Override
                        public void onGlobalLayout() {
                            LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) bottomView.getLayoutParams();
                            params.height = getBottomStatusHeight(ActivityShopIndex.this);
                            bottomView.setLayoutParams(params);
                            bottomView.setVisibility(View.VISIBLE);
                        }
                    });
        }

這樣我們就成功將虛擬按鍵欄也被沈浸的問題解決了。

作者 水木

Android中沈浸式狀態欄的應用