Android沉浸式通知栏开源库SystemBarTint源码解析
16lz
2021-01-24
前一段时间我写了一篇关于沉浸式的文章: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 = "status_bar_height"; private static final String NAV_BAR_HEIGHT_RES_NAME = "navigation_bar_height"; private static final String NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME = "navigation_bar_height_landscape"; private static final String NAV_BAR_WIDTH_RES_NAME = "navigation_bar_width"; private static final String SHOW_NAV_BAR_RES_NAME = "config_showNavigationBar"; 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 >= 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 >= 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 >= 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, "bool", "android"); if (resourceId != 0) { boolean hasNav = res.getBoolean(resourceId); // check override flag (see static block) if ("1".equals(sNavBarOverride)) { hasNav = false; } else if ("0".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, "dimen", "android"); if (resourceId > 0) { result = res.getDimensionPixelSize(resourceId); } return result; } @SuppressLint("NewApi") private float getSmallestWidthDp(Activity activity) { DisplayMetrics metrics = new DisplayMetrics(); if (Build.VERSION.SDK_INT >= 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); }
更多相关文章
- Android(安卓)4.0 framework源码修改编译,模拟器运行不起来——解
- Android中直播视频技术探究之---视频直播服务端环境搭建(Nginx+R
- 自定义ListView背景(解决了拖动变黑的效果)
- Android(安卓)源码中的设计模式
- Android(安卓)实战 (一) Remote Service,Thread,Handler,Broadcast
- Android(安卓)源码本地编译脚本 & 编译Android系统
- Android(安卓)9 (P)之init进程启动源码分析指南之三
- Android(安卓)JSBridge的原理与实现
- android简易画图板与五子棋