Github上最好用的Android状态栏、导航栏库!
刘望舒
共 27868字,需浏览 56分钟
·
2021-04-12 12:34
Android
加入安卓技术群作者:Zackratos
https://juejin.cn/user/1275089219488526/posts
前言
https://github.com/Zackratos/UltimateBarX
关于命名
实现方案
https://blog.csdn.net/guolin_blog/article/details/51763825
private fun test() {
window?.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
window?.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
}
private fun test() {
val flag = (View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
window?.decorView?.systemUiVisibility = flag
window?.statusBarColor = Color.TRANSPARENT
window?.navigationBarColor = Color.TRANSPARENT
}
private fun test() {
window?.statusBarColor = Color.RED
window?.navigationBarColor = Color.RED
}
private fun test() {
window?.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
window?.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
val decorView = window?.decorView as FrameLayout?
val contentView = decorView?.findViewById<ViewGroup>(android.R.id.content)?.getChildAt(0)
contentView?.fitsSystemWindows = true
val statusBarView = View(this)
statusBarView.setBackgroundColor(Color.RED)
val statusBarLP = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight())
statusBarLP.gravity = Gravity.TOP
decorView?.addView(statusBarView, statusBarLP)
val navigationBarView = View(this)
navigationBarView.setBackgroundColor(Color.RED)
val navigationBarLP = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getNavigationBarHeight())
navigationBarLP.gravity = Gravity.BOTTOM
decorView?.addView(navigationBarView, navigationBarLP)
}
private fun test(
statusBarFitWindow: Boolean,
@ColorInt statusBarColor: Int,
navigationBarFitWindow: Boolean,
@ColorInt navigationBarColor: Int
) {
transparentBar()
setStatusBarView(statusBarFitWindow, statusBarColor)
setNavigationBarView(navigationBarFitWindow, navigationBarColor)
}
private fun transparentBar() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
val flag = (View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
window?.decorView?.systemUiVisibility = flag
window?.statusBarColor = Color.TRANSPARENT
window?.navigationBarColor = Color.TRANSPARENT
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
window?.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
window?.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
}
val decorView = window?.decorView as FrameLayout?
val contentView = decorView?.findViewById<ViewGroup>(android.R.id.content)?.getChildAt(0)
contentView?.fitsSystemWindows = false
decorView?.clipToPadding = false
}
private fun setStatusBarView(statusBarFitWindow: Boolean, @ColorInt statusBarColor: Int) {
val decorView = window?.decorView as FrameLayout?
var statusBarView = decorView?.findViewWithTag<View>("status_bar")
if (statusBarView == null) {
statusBarView = View(this)
statusBarView.tag = "status_bar"
}
statusBarView.setBackgroundColor(statusBarColor)
val statusBarLP =
FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight())
if (statusBarFitWindow) {
statusBarLP.topMargin = -getStatusBarHeight()
decorView?.setPadding(0, getStatusBarHeight(), 0, decorView.paddingBottom)
} else {
statusBarLP.topMargin = 0
decorView?.setPadding(0, 0, 0, decorView.paddingBottom)
}
statusBarLP.gravity = Gravity.TOP
decorView?.addView(statusBarView, statusBarLP)
}
private fun setNavigationBarView(navigationBarFitWindow: Boolean, @ColorInt navigationBarColor: Int) {
val decorView = window?.decorView as FrameLayout?
var navigationBarView = decorView?.findViewWithTag<View>("navigation_bar")
if (navigationBarView == null) {
navigationBarView = View(this)
navigationBarView.tag = "navigation_bar"
}
navigationBarView.setBackgroundColor(navigationBarColor)
val navigationBarLP =
FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getNavigationBarHeight())
if (navigationBarFitWindow) {
navigationBarLP.bottomMargin = -getNavigationBarHeight()
decorView?.setPadding(0, decorView.paddingTop, 0, getNavigationBarHeight())
} else {
navigationBarLP.bottomMargin = 0
decorView?.setPadding(0, decorView.paddingTop, 0, 0)
}
navigationBarLP.gravity = Gravity.BOTTOM
decorView?.addView(navigationBarView, navigationBarLP)
}
light 模式
private fun test() {
val flag = (View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
or View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR)
window?.decorView?.systemUiVisibility = flag
window?.statusBarColor = Color.TRANSPARENT
window?.navigationBarColor = Color.TRANSPARENT
}
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
private fun systemUiFlag(statusBarLight: Boolean, navigationBarLight: Boolean): Int {
var flag = (View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> {
if (statusBarLight) flag = flag or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
if (navigationBarLight) flag = flag or View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
}
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> {
if (statusBarLight) flag = flag or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
}
}
return flag
}
internal class UltimateBarXObserver: LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun onDestroy(owner: LifecycleOwner) {
UltimateBarXManager.getInstance().removeAllData(owner)
}
}
private fun test() {
addObserver(UltimateBarXObserver())
}
适配全面屏导航栏
private fun putOriginColor() {
val navigationBarColor = window?.navigationBarColor ?: Color.TRANSPARENT
originColorMap[this] = navigationBarColor
val navConfig = getNavigationBarConfig(this)
navConfig.light = calculateLight(navigationBarColor)
putNavigationBarConfig(this, navConfig)
}
private fun calculateLight(@ColorInt color: Int) = color > (Color.BLACK + Color.WHITE / 2)
在Fragment中使用
View的父布局
private fun setStatusBarView(statusBarFitWindow: Boolean, @ColorInt statusBarColor: Int) {
val rootView = requireView() as RelativeLayout
var statusBarView = rootView.findViewWithTag<View>("status_bar")
if (statusBarView == null) {
statusBarView = View(requireContext())
statusBarView.tag = "status_bar"
}
statusBarView.setBackgroundColor(statusBarColor)
val statusBarLP =
RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight())
if (statusBarFitWindow) {
statusBarLP.topMargin = -getStatusBarHeight()
rootView.setPadding(0, getStatusBarHeight(), 0, rootView.paddingBottom)
} else {
statusBarLP.topMargin = 0
rootView.setPadding(0, 0, 0, rootView.paddingBottom)
}
statusBarLP.addRule(RelativeLayout.ALIGN_PARENT_TOP)
rootView.addView(statusBarView, statusBarLP)
}
private fun setNavigationBarView(navigationBarFitWindow: Boolean, @ColorInt navigationBarColor: Int) {
val rootView = requireView() as RelativeLayout
var navigationBarView = rootView.findViewWithTag<View>("navigation_bar")
if (navigationBarView == null) {
navigationBarView = View(requireContext())
navigationBarView.tag = "navigation_bar"
}
navigationBarView.setBackgroundColor(navigationBarColor)
val navigationBarLP =
RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getNavigationBarHeight())
if (navigationBarFitWindow) {
navigationBarLP.bottomMargin = -getNavigationBarHeight()
rootView.setPadding(0, rootView.paddingTop, 0, getNavigationBarHeight())
} else {
navigationBarLP.bottomMargin = 0
rootView.setPadding(0, rootView.paddingTop, 0, 0)
}
navigationBarLP.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM)
rootView.addView(navigationBarView, navigationBarLP)
}
private fun setStatusBarView(statusBarFitWindow: Boolean, @ColorInt statusBarColor: Int) {
val rootView = requireView() as ViewGroup
val paddingTop = if (statusBarFitWindow) getStatusBarHeight() else 0
rootView.setPadding(0, paddingTop, 0, rootView.paddingBottom)
var statusBarView = rootView.findViewWithTag<View>("status_bar")
if (statusBarView == null) {
statusBarView = View(requireContext())
statusBarView.tag = "status_bar"
}
statusBarView.setBackgroundColor(statusBarColor)
rootView.addView(statusBarView, ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight())
statusBarView.post { statusBarView.translationY = -statusBarView.top.toFloat() }
}
private fun setNavigationBarView(navigationBarFitWindow: Boolean, @ColorInt navigationBarColor: Int) {
val rootView = requireView() as ViewGroup
val paddingBottom = if (navigationBarFitWindow) getNavigationBarHeight() else 0
rootView.setPadding(0, rootView.paddingTop, 0, paddingBottom)
var navigationBarView = rootView.findViewWithTag<View>("navigation_bar")
if (navigationBarView == null) {
navigationBarView = View(requireContext())
navigationBarView.tag = "navigation_bar"
}
navigationBarView.setBackgroundColor(navigationBarColor)
rootView.addView(navigationBarView, ViewGroup.LayoutParams.MATCH_PARENT, getNavigationBarHeight())
navigationBarView.post { navigationBarView.translationY = (rootView.height - navigationBarView.bottom).toFloat() }
}
private fun addFrameLayoutWrapper(): ViewGroup {
val view = requireView()
if (view is FrameLayout || view is RelativeLayout) return view as ViewGroup
val flWrapper = FrameLayout(requireContext())
flWrapper.setTag(androidx.fragment.R.id.fragment_container_view_tag, this)
val parent = view.parent
if (parent is ViewGroup) {
val index = parent.indexOfChild(view)
parent.removeViewAt(index)
parent.addView(flWrapper, index)
}
flWrapper.addView(view)
val fragmentViewFiled = Fragment::class.java.getDeclaredField("mView")
fragmentViewFiled.isAccessible = true
fragmentViewFiled.set(this, flWrapper)
return flWrapper
}
internal class UltimateBarXObserver: LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun onDestroy(owner: LifecycleOwner) {
UltimateBarXManager.getInstance().removeAllData(owner)
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun onResume(owner: LifecycleOwner) {
if (owner is Fragment) {
val staDefault = UltimateBarXManager.getInstance().getStatusBarDefault(owner)
val navDefault = UltimateBarXManager.getInstance().getNavigationBarDefault(owner)
if (staDefault) {
UltimateBarX.get(owner).applyStatusBar()
}
if (navDefault) {
UltimateBarX.get(owner).applyNavigationBar()
}
}
}
}
github上最好用的
状态栏和导航栏彻底解藕,单独设置,互不影响 同一个 Activity 或 Fragment 可以多次设置不同的效果
private fun test() {
UltimateBarX.with(this) // 在当前 Activity/Fragment 生效
.fitWindow(true) // 是否侵入状态栏 (true: 不侵入)
.color(Color.BLACK) // 状态栏颜色(色值)
.colorRes(R.color.deepSkyBlue) // 状态栏颜色(资源 id)
.drawableRes(R.drawable.bg_gradient) // 状态栏背景(drawable 资源)
.light(false) // light 模式(true: 字体变灰)
.applyStatusBar() // 应用到状态栏
}
推荐阅读
• 耗时2年,Android进阶三部曲第三部《Android进阶指北》出版!
• 『BATcoder』做了多年安卓还没编译过源码?一个视频带你玩转!
BATcoder技术群,让一部分人先进大厂
你好,我是刘望舒,腾讯云最具价值专家TVP,著有畅销书《Android进阶之光》《Android进阶解密》《Android进阶指北》,蝉联四届电子工业出版社年度优秀作者,谷歌开发者社区特邀讲师。
前华为面试官,现大厂技术负责人。
想要加入 BATcoder技术群,公号回复Android
即可。
为了防止失联,欢迎关注我的小号
更文不易,点个“在看”支持一下👇
评论