美文网首页
StatusBar 设置透明状态栏和自定义颜色

StatusBar 设置透明状态栏和自定义颜色

作者: 因为我的心 | 来源:发表于2021-07-31 16:57 被阅读0次

    一、前言:

    特点:

    • 透明状态栏
    • 状态栏背景颜色
    • 状态栏文字颜色(亮|暗色模式)
    • 支持Activity/Fragment/DrawerLayout
    • Kotlin特性
    • 一行代码实现
    • 文档详细, Demo简单
      注意:StatusBar 只只支持Kotlin状态栏的适配。

    二、使用

    1、在项目根目录的 build.gradle 添加仓库

    allprojects {
        repositories {
            // ...
            maven { url 'https://jitpack.io' }
        }
    }
    

    2、在 module 的 build.gradle 添加依赖

     implementation 'com.github.liangjingkanji:StatusBar:2.0.0'
    

    3、使用1:

    open class BaseActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
              //直接调用,参数1是背景色,参数2是字体颜色(白色/黑色)
              immersive(resources.getColor(R.color.color_FFEC5C46), false)
        }
    }
    

    4、使用2:

    要求图片的一部分作为状态栏的背景

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_immerse_image)
        immersive()
    }
    
    图片.png

    如果这里你使用的是ActionBar, 则应该给ActionBar设置透明背景

    图片.png
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_immerse_image)
    
        immersive()
        setActionBarTransparent() // 给ActionBar设置透明背景
    }
    

    5、状态栏字体颜色

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_dark_status_bar)
        immersive(Color.YELLOW, true)
    }
    
    图片.png

    immersive这个函数还可以传入View进去, 就会自动使用View的背景色作为状态栏颜色.

    class MainActivity : BaseMenuActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            toolbar.inflateMenu(R.menu.menu_main)
            toolbar.setOnMenuItemClickListener { onOptionsItemSelected(it) }
            immersive(toolbar)
            // or dark status bar
            // immersive(toolbar, true)
        }
    }
    

    6、辅助函数

    图片.png

    三、源码:

    private const val COLOR_TRANSPARENT = 0
    
    // <editor-fold desc="透明状态栏">
    
    
    /**
     * 半透明状态栏
     * 会导致键盘遮挡输入框, 为根布局设置[View.setFitsSystemWindows]为true可以解决
     *
     * @param translucent 是否显示透明状态栏
     * @param darkMode 是否显示暗色状态栏文字颜色
     */
    fun Activity.translucent(
        translucent: Boolean = true,
        darkMode: Boolean? = null
    ) {
        if (Build.VERSION.SDK_INT >= 19) {
            if (translucent) {
                window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
            } else {
                window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
            }
        }
        if (darkMode != null) {
            darkMode(darkMode)
        }
    }
    
    /**
     * 使用视图的背景色作为状态栏颜色
     */
    fun Activity.immersive(view: View, darkMode: Boolean? = null) {
        val background = view.background
        if (background is ColorDrawable) {
            immersive(background.color, darkMode)
        }
    }
    
    /**
     * 设置透明状态栏或者状态栏颜色, 会导致状态栏覆盖界面
     *
     * 如果不指定状态栏颜色则会应用透明状态栏(全屏属性), 会导致键盘遮挡输入框
     *
     * @param color 状态栏颜色, 不指定则为透明状态栏
     * @param darkMode 是否显示暗色状态栏文字颜色
     */
    @SuppressLint("ObsoleteSdkInt")
    fun Activity.immersive(@ColorInt color: Int = COLOR_TRANSPARENT, darkMode: Boolean? = null) {
        when {
            Build.VERSION.SDK_INT >= 21 -> {
                when (color) {
                    COLOR_TRANSPARENT -> {
                        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
                        var systemUiVisibility = window.decorView.systemUiVisibility
                        systemUiVisibility = systemUiVisibility or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                        systemUiVisibility = systemUiVisibility or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                        window.decorView.systemUiVisibility = systemUiVisibility
                        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
                        window.statusBarColor = color
                    }
                    else -> {
                        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
                        var systemUiVisibility = window.decorView.systemUiVisibility
                        systemUiVisibility =
                            systemUiVisibility and View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                        systemUiVisibility = systemUiVisibility and View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                        window.decorView.systemUiVisibility = systemUiVisibility
                        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
                        window.statusBarColor = color
                    }
                }
            }
            Build.VERSION.SDK_INT >= 19 -> {
                window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
                if (color != COLOR_TRANSPARENT) {
                    setTranslucentView(window.decorView as ViewGroup, color)
                }
            }
        }
        if (darkMode != null) {
            darkMode(darkMode)
        }
    }
    
    /**
     * 获取颜色资源值来设置状态栏
     */
    fun Activity.immersiveRes(@ColorRes color: Int, darkMode: Boolean? = null) =
        immersive(resources.getColor(color), darkMode)
    
    // </editor-fold>
    
    
    //<editor-fold desc="暗色模式">
    
    
    /**
     * 开关状态栏暗色模式, 并不会透明状态栏, 只是单纯的状态栏文字变暗色调.
     *
     * @param darkMode 状态栏文字是否为暗色
     */
    fun Activity.darkMode(darkMode: Boolean = true) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            var systemUiVisibility = window.decorView.systemUiVisibility
            systemUiVisibility = if (darkMode) {
                systemUiVisibility or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
            } else {
                systemUiVisibility and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv()
            }
            window.decorView.systemUiVisibility = systemUiVisibility
        }
    }
    
    //</editor-fold>
    
    // <editor-fold desc="间距">
    
    /**
     * 增加View的上内边距, 增加高度为状态栏高度, 防止视图和状态栏重叠
     * 如果是RelativeLayout设置padding值会导致centerInParent等属性无法正常显示
     *
     * @param remove true: paddingTop = 状态栏高度
     *               false: paddingTop = 0
     */
    fun View.statusPadding(remove: Boolean = false) {
        if (this is RelativeLayout) {
            throw UnsupportedOperationException("Unsupported set statusPadding for RelativeLayout")
        }
        if (Build.VERSION.SDK_INT >= 19) {
            val statusBarHeight = context.statusBarHeight
            val lp = layoutParams
            if (lp != null && lp.height > 0) {
                lp.height += statusBarHeight //增高
            }
            if (remove) {
                if (paddingTop < statusBarHeight) return
                setPadding(
                    paddingLeft, paddingTop - statusBarHeight,
                    paddingRight, paddingBottom
                )
            } else {
                if (paddingTop >= statusBarHeight) return
                setPadding(
                    paddingLeft, paddingTop + statusBarHeight,
                    paddingRight, paddingBottom
                )
            }
        }
    }
    
    
    /**
     * 创建假的透明栏
     */
    private fun Context.setTranslucentView(container: ViewGroup, color: Int) {
        if (Build.VERSION.SDK_INT >= 19) {
            var simulateStatusBar: View? = container.findViewById(android.R.id.custom)
            if (simulateStatusBar == null && color != 0) {
                simulateStatusBar = View(container.context)
                simulateStatusBar.id = android.R.id.custom
                val lp = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight)
                container.addView(simulateStatusBar, lp)
            }
            simulateStatusBar?.setBackgroundColor(color)
        }
    }
    
    //</editor-fold>
    
    //<editor-fold desc="ActionBar">
    
    /**
     * 设置ActionBar的背景颜色
     */
    fun AppCompatActivity.setActionBarBackground(@ColorInt color: Int) {
        supportActionBar?.setBackgroundDrawable(ColorDrawable(color))
    }
    
    fun AppCompatActivity.setActionBarBackgroundRes(@ColorRes color: Int) {
        supportActionBar?.setBackgroundDrawable(ColorDrawable(resources.getColor(color)))
    }
    
    /**
     * 设置ActionBar的背景颜色为透明
     */
    fun AppCompatActivity.setActionBarTransparent() {
        supportActionBar?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
    }
    //</editor-fold>
    
    // <editor-fold desc="辅助">
    
    /**
     * 显示或隐藏导航栏, 系统开启可以隐藏, 系统未开启不能开启
     *
     * @param enabled 是否显示导航栏
     */
    fun Activity.setNavigationBar(enabled: Boolean = true) {
        if (Build.VERSION.SDK_INT in 12..18) {
            if (enabled) {
                window.decorView.systemUiVisibility = View.VISIBLE
            } else {
                window.decorView.systemUiVisibility = View.GONE
            }
        } else if (Build.VERSION.SDK_INT >= 19) {
            val systemUiVisibility = window.decorView.systemUiVisibility
            if (enabled) {
                window.decorView.systemUiVisibility =
                    systemUiVisibility and View.SYSTEM_UI_FLAG_HIDE_NAVIGATION and View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
            } else {
                window.decorView.systemUiVisibility = systemUiVisibility or
                        View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
            }
        }
    }
    
    /**
     * 设置是否全屏
     *
     * @param enabled 是否全屏显示
     */
    fun Activity.setFullscreen(enabled: Boolean = true) {
        val systemUiVisibility = window.decorView.systemUiVisibility
        window.decorView.systemUiVisibility = if (enabled) {
            systemUiVisibility or View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
        } else {
            systemUiVisibility or View.SYSTEM_UI_FLAG_LAYOUT_STABLE and View.SYSTEM_UI_FLAG_FULLSCREEN.inv()
        }
    }
    
    /**
     * 是否有导航栏
     */
    val Activity?.isNavigationBar: Boolean
        get() {
            this ?: return false
            val vp = window.decorView as? ViewGroup
            if (vp != null) {
                for (i in 0 until vp.childCount) {
                    vp.getChildAt(i).context.packageName
                    if (vp.getChildAt(i).id != -1 && "navigationBarBackground" ==
                        resources.getResourceEntryName(vp.getChildAt(i).id)
                    ) return true
                }
            }
            return false
        }
    
    /**
     * 如果当前设备存在导航栏返回导航栏高度, 否则0
     */
    val Context?.navigationBarHeight: Int
        get() {
            this ?: return 0
            val resourceId: Int = resources.getIdentifier("navigation_bar_height", "dimen", "android")
            var height = 0
            if (resourceId > 0) {
                height = resources.getDimensionPixelSize(resourceId)
            }
            return height
        }
    
    
    /**
     * 状态栏高度
     */
    val Context?.statusBarHeight: Int
        get() {
            this ?: return 0
            var result = 24
            val resId = resources.getIdentifier("status_bar_height", "dimen", "android")
            result = if (resId > 0) {
                resources.getDimensionPixelSize(resId)
            } else {
                TypedValue.applyDimension(
                    TypedValue.COMPLEX_UNIT_DIP,
                    result.toFloat(), Resources.getSystem().displayMetrics
                ).toInt()
            }
            return result
        }
    // </editor-fold>
    

    参考:https://liangjingkanji.github.io/StatusBar/other.html

    相关文章

      网友评论

          本文标题:StatusBar 设置透明状态栏和自定义颜色

          本文链接:https://www.haomeiwen.com/subject/ydkkvltx.html