美文网首页Android技术进阶-今晚吃啥子? -罗非鱼。UI
侧滑返回适配状态栏,避免内容布局与状态栏的“撕裂”效果

侧滑返回适配状态栏,避免内容布局与状态栏的“撕裂”效果

作者: 孔鹏飞 | 来源:发表于2021-05-20 18:11 被阅读0次

    前言

    所谓撕裂这里指的是侧滑返回上一级页面时,状态栏不随内容布局移动,造成状态栏和内容布局不联动,相分离的问题。

    小红书APP设置页面 微信APP页面
    xhs.gif wx.gif

    问题分析

    此处以小红书APP设置页面为例进行分析,通过uiautomatorviewer工具查看页面布局,布局结构如下:

    小红书设置页面.png
    • 页面使用的是系统状态栏(idandroid:id/statusBarBackground),状态栏背景颜色为白色。
    • 侧滑布局不包含系统状态栏,侧滑返回时,内容布局在滑动,系统状态栏固定不动。

    解决办法

    要想使侧滑时状态栏和内容布局一起滑动,一般的解决办法如下:

    • 设置系统状态栏背景颜色为透明
    • 页面布局延伸到状态栏区域,由页面负责状态栏的绘制,侧滑布局包含该状态栏区域
    • 自定义View填充状态栏区域或设置页面的顶部布局如TitleBar的topPadding为状态栏高度

    代码实现

    此处假设使用的侧滑控件为SwipeBackLayout,此控件是在onPostCreate方法里添加侧滑布局,因此我们覆盖onPostCreate方法,在此方法里适配状态栏即可。

    • 基类BaseActivity继承SwipeBackActivity,定义一些状态栏和导航栏相关的方法。
    
        /**
         * 获取自定义的状态栏View,如为null,则采用默认的View填充状态栏区域
         */
        protected open fun getStatusBarView(): View? {
            return null
        }
    
        /**
         * 状态栏颜色
         */
        protected open fun statusBarColor(): Int {
            return R.color.white
        }
    
        /**
         * 导航栏颜色
         */
        protected open fun navigationBarColor(): Int {
            return R.color.white
        }
    
        /**
         * 状态栏字体颜色是否高亮
         */
        protected open fun statusBarDarkFont(): Boolean {
            return true
        }
    
        /**
         * 导航栏字体颜色是否高亮
         */
        protected open fun navigationBarDarkFont(): Boolean {
            return true
        }
    
    
    • 覆盖onPostCreate方法,设置状态栏和导航栏背景和字体颜色。
        @Override
        override fun onPostCreate(savedInstanceState: Bundle?) {
            super.onPostCreate(savedInstanceState)
    
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
            /**
             * 设置系统状态栏背景颜色为透明
             */
            window.statusBarColor = Color.TRANSPARENT
            var uiFlags = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                /**
                 * 高亮状态栏字体
                 */
                if(statusBarDarkFont()) {
                    uiFlags = uiFlags or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
                }
            }
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                /**
                 * 高亮导航栏字体
                 */
                if(navigationBarDarkFont()) {
                    uiFlags = uiFlags or View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
                }
            }
            window.decorView.systemUiVisibility = uiFlags
    
            /**
             * 获取状态栏高度
             */
            val statusBarHeight = ScreenHelper.getStatusbarHeight(this)
    
            /**
             * 获取状态栏View
             */
            var statusBarView=getStatusBarView()
            if(statusBarView==null) {
                statusBarView = View(this)
                statusBarView.id = R.id.status_bar_id
                val contentView = window.decorView.findViewById(android.R.id.content) as ViewGroup
                /**
                 * 设置Padding
                 */
                contentView.getChildAt(0).setPadding(0, statusBarHeight, 0, 0)
                /**
                 * 添加状态栏布局
                 */
                contentView.addView(statusBarView, ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight))
            }
            else{
                setStatusBarHeight(statusBarView)
            }
            statusBarView.setBackgroundColor(ContextCompat.getColor(applicationContext,statusBarColor()))
            window.navigationBarColor = ContextCompat.getColor(applicationContext,navigationBarColor())
        }
    
    /**
     * 设置View高度为状态栏高度
     */
    fun setStatusBarHeight(view:View?) {
        if(view==null){
            return
        }
        val fixHeight=ScreenHelper.getStatusbarHeight(this)
        var layoutParams = view.layoutParams
        if (layoutParams == null) {
            layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
        }
        if (layoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT || layoutParams.height == ViewGroup.LayoutParams.MATCH_PARENT) {
            val finalLayoutParams = layoutParams
            view.post(Runnable {
                finalLayoutParams.height = fixHeight
                view.layoutParams = finalLayoutParams
            })
        } else {
            layoutParams.height = fixHeight
            view.layoutParams = layoutParams
        }
    }
    

    实现效果

    1 2
    1.gif 2.gif

    GitHub

    https://github.com/kongpf8848/AndroidWorld

    相关文章

      网友评论

        本文标题:侧滑返回适配状态栏,避免内容布局与状态栏的“撕裂”效果

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