Android沉浸式通知欄開源庫SystemBarTint源碼解析

分類:技術 時間:2016-10-25

前一段時間我寫了一篇關于沉浸式的文章: Android實現沉浸式狀態欄的那些坑

當時只是知道 SystemBarTint 的存在,并沒有去了解它的實現效果和原理,因為搜Android沉浸式時好多都提到這個開源庫,還以為很強大、很深奧,就沒敢倉促的去看源碼。今天把SystemBarTint拉下來一看,發現這個庫僅僅只有一個類:SystemBarTintManager,全篇通讀下來發現原理也是相當簡單:就是在狀態欄填充一個指定顏色、與狀態欄等高的view

private void setupStatusBarView(Activity activity) {
        Window win = activity.getWindow();
        ViewGroup decorViewGroup = (ViewGroup) win.getDecorView();//拿到decorview

        mStatusBarTintView = new View(context);
        LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, mConfig.getStatusBarHeight());
        params.gravity = Gravity.TOP;
        if (mNavBarAvailable  !mConfig.isNavigationAtBottom()) {
            params.rightMargin = mConfig.getNavigationBarWidth();
        }
        mStatusBarTintView.setLayoutParams(params);
        mStatusBarTintView.setBackgroundColor(DEFAULT_TINT_COLOR);
        mStatusBarTintView.setVisibility(View.GONE);
        // 將純色的StatusBarTintView添加到decorview
        decorViewGroup.addView(mStatusBarTintView);
    }

稍微修改了一點源碼,便于理解。導航欄的實現也是一樣的。

這樣看來,這個庫僅僅是用view填充狀態欄,雖然可以設置顏色、drawable,但是跟有些需求還是有出入的,所以還是可以看看另一種方案:讓view延伸到狀態欄,然后設置狀態欄等高的padding。

可以參考 http://blog.csdn.net/brian512/article/details/52096445

SystemBarTint里面對于狀態欄和導航欄高度的獲取方法還是可以學習一下的,那么多人用過沒問題,應該算是適配不錯的:

private static final String STATUS_BAR_HEIGHT_RES_NAME = quot;status_bar_heightquot;;
        private static final String NAV_BAR_HEIGHT_RES_NAME = quot;navigation_bar_heightquot;;
        private static final String NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME = quot;navigation_bar_height_landscapequot;;
        private static final String NAV_BAR_WIDTH_RES_NAME = quot;navigation_bar_widthquot;;
        private static final String SHOW_NAV_BAR_RES_NAME = quot;config_showNavigationBarquot;;


        private int getStatusBarHeightHeight(Context context) {
            return getInternalDimensionSize(context.getResources(), STATUS_BAR_HEIGHT_RES_NAME);
        }
        @TargetApi(14)
        private int getActionBarHeight(Context context) {
            int result = 0;
            if (Build.VERSION.SDK_INT gt;= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                TypedValue tv = new TypedValue();
                context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true);
                result = TypedValue.complexToDimensionPixelSize(tv.data, context.getResources().getDisplayMetrics());
            }
            return result;
        }

        @TargetApi(14)
        private int getNavigationBarHeight(Context context) {
            Resources res = context.getResources();
            int result = 0;
            if (Build.VERSION.SDK_INT gt;= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                if (hasNavBar(context)) {
                    String key;
                    if (mInPortrait) {
                        key = NAV_BAR_HEIGHT_RES_NAME;
                    } else {
                        key = NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME;
                    }
                    return getInternalDimensionSize(res, key);
                }
            }
            return result;
        }

        @TargetApi(14)
        private int getNavigationBarWidth(Context context) {
            Resources res = context.getResources();
            int result = 0;
            if (Build.VERSION.SDK_INT gt;= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                if (hasNavBar(context)) {
                    return getInternalDimensionSize(res, NAV_BAR_WIDTH_RES_NAME);
                }
            }
            return result;
        }

        @TargetApi(14)
        private boolean hasNavBar(Context context) {
            Resources res = context.getResources();
            int resourceId = res.getIdentifier(SHOW_NAV_BAR_RES_NAME, quot;boolquot;, quot;androidquot;);
            if (resourceId != 0) {
                boolean hasNav = res.getBoolean(resourceId);
                // check override flag (see static block)
                if (quot;1quot;.equals(sNavBarOverride)) {
                    hasNav = false;
                } else if (quot;0quot;.equals(sNavBarOverride)) {
                    hasNav = true;
                }
                return hasNav;
            } else { // fallback
                return !ViewConfiguration.get(context).hasPermanentMenuKey();
            }
        }

        private int getInternalDimensionSize(Resources res, String key) {
            int result = 0;
            int resourceId = res.getIdentifier(key, quot;dimenquot;, quot;androidquot;);
            if (resourceId gt; 0) {
                result = res.getDimensionPixelSize(resourceId);
            }
            return result;
        }

        @SuppressLint(quot;NewApiquot;)
        private float getSmallestWidthDp(Activity activity) {
            DisplayMetrics metrics = new DisplayMetrics();
            if (Build.VERSION.SDK_INT gt;= Build.VERSION_CODES.JELLY_BEAN) {
                activity.getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
            } else {
                // TODO this is not correct, but we don't really care pre-kitkat
                activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
            }
            float widthDp = metrics.widthPixels / metrics.density;
            float heightDp = metrics.heightPixels / metrics.density;
            return Math.min(widthDp, heightDp);
        }

Tags: 開源 安卓開發

文章來源:http://www.jianshu.com/p/60a86d6ac5c8


ads
ads

相關文章
ads

相關文章

ad