前一段時間我寫了一篇關于沉浸式的文章:
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