美文网首页
Android中三星折叠屏在多窗口运行时侵入式状态栏的适配问题

Android中三星折叠屏在多窗口运行时侵入式状态栏的适配问题

作者: 馒头炖土豆 | 来源:发表于2023-10-08 15:27 被阅读0次

问题描述:

当页面使用fitsSystemWindow属性时,目的之一是想让窗口自动适配状态栏,但是目前发现有特殊设备在特殊情况下会丢失状态栏(的高度),比如三星折叠屏在多窗口运行时fitsSystemWindow属性不能生效,具体现象是顶部内容被一个横杠遮挡

解决方案:

运行时获取statusBar的高度,并修正页面根布局的高度

工具类代码如下:

import android.app.Activity
import android.content.Context
import android.graphics.Color
import android.os.Build
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.widget.FrameLayout
import androidx.annotation.ColorRes
import com.kongfz.app.core.R
import com.kongfz.app.core.common.drive.extend.catchExceptions
import com.kongfz.app.core.common.utils.blankj.util.Utils

object StatusBarUtils {
    @Target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.TYPE)
    @Retention(AnnotationRetention.SOURCE)
    annotation class FakeStatusBarCfg {
        companion object {
            //永远不需要,上层自行调整布局高度。
            //适用页面:顶部是沉浸式图片类型
            const val NEVER_NEED = 0

            //永远需要
            //适用页面:普通的顶部,并且没有使用fitsSystemWindow
            const val ALWAYS_NEED = 1

            //如果丢失就需要,否则不需要
            //适用页面:普通的顶部,并且使用了fitsSystemWindow
            const val NEED_WHEN_LOST = 2

        }
    }

    fun setStatusBarFontIconLight(activity: Activity, isLightIcon: Boolean) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            val decorView = activity.window.decorView
            val option = (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    or View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
            decorView.systemUiVisibility = option
            if (isLightIcon) {
                activity.window.statusBarColor = Color.TRANSPARENT
            } else {
                activity.window.statusBarColor = Color.WHITE
            }
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            val localLayoutParams = activity.window.attributes
            localLayoutParams.flags =
                WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS or localLayoutParams.flags
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !isLightIcon) {
            //android6.0以后可以对状态栏文字颜色和图标进行修改
            activity.window.decorView.systemUiVisibility =
                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
        }
    }

    fun getStatusBarHeight(context: Context): Int {
        val resources = context.resources
        val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android")
        return resources.getDimensionPixelSize(resourceId)
    }

    @JvmStatic
    val statusBarHeight: Int
        get() {
            val resources =
                Utils.getApp().resources
            val resourceId =
                resources.getIdentifier("status_bar_height", "dimen", "android")
            return resources.getDimensionPixelSize(resourceId)
        }

    /**
     * 运行时获取statusBar的高度,并修正根布局的h
     */
    @JvmStatic
    fun fixStatusHeight(view: View) {
        val h = getStatusBarHeight(Utils.getApp())
        val lp = view.layoutParams as ViewGroup.MarginLayoutParams
        lp.setMargins(0, h, 0, 0)
        view.layoutParams = lp
    }

    fun tryAddingFakeStatusBar(
        activity: Activity,
        fakeStatusBarCfg: @FakeStatusBarCfg Int,
        rootView: ViewGroup,
        @ColorRes color: Int
    ) {
        if (fakeStatusBarCfg == FakeStatusBarCfg.NEED_WHEN_LOST) {
            addFakeStatusBarWhenLost(activity, rootView, color)
        } else if (fakeStatusBarCfg == FakeStatusBarCfg.ALWAYS_NEED) {
            addFakeStatusBar(activity, rootView, color)
        }
    }

    private fun addFakeStatusBarWhenLost(
        activity: Activity,
        rootView: ViewGroup,
        @ColorRes color: Int
    ) {
        if (willLossStatusBar(activity))
            addFakeStatusBar(activity, rootView, color)
    }

    private fun addFakeStatusBar(
        activity: Activity,
        rootView: ViewGroup,
        @ColorRes color: Int
    ) {
        catchExceptions {
            val decorView = activity.window.decorView as ViewGroup
            decorView.findViewById<View>(R.id.un_status_bar_view)?.let {
                decorView.removeView(it)
            }
            val view = View(activity).apply {
                id = R.id.un_status_bar_view
                layoutParams =
                    ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight)
                setBackgroundResource(color)
            }
            decorView.addView(view)
            //添加status view后,需将原始布局下移
            val lp = rootView.layoutParams as FrameLayout.LayoutParams
            lp.topMargin = statusBarHeight
        }
    }

    /**
     * 状态栏是否会丢失
     *
     * 少量特殊设备在多窗口模式下运行,会丢失状态栏!
     *
     * 这个方法上层可以直接使用,自行处理根布局的高度
     *
     */
    fun willLossStatusBar(activity: Activity): Boolean {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            //这个条件以后也许会变!
            if (activity.isInMultiWindowMode
                && Build.MODEL == "SM-F9160"
//                && Build.VERSION.SDK_INT == 33
            ) {
                //SM-F9160是三星折叠屏手机,它在多窗口下,会丢失status bar
                return true
            }
        }
        return false
    }
}

实际使用:

activity的基类

 private fun initStatus() {
        StatusBarUtils.tryAddingFakeStatusBar(
            this,
            fakeStatusBarCfg(), //StatusBarUtils中FakeStatusBarCfg的值
            baseBinding.root,
            statusBarColor() //沉浸式状态栏的颜色
        )
       
        
         //设置沉浸状态栏——根据实际情况来写
            immersionBar = ImmersionBar.with(this)
            immersionBar?.run {
                statusBarColor(statusBarColor())
                statusBarDarkFont(statusBarDarkFont())
                init()  
     
    }

//子类复写
 protected open fun statusBarColor(): Int {
        return R.color.transparent
    }

//这个方法为Java代码,其余为Kotlin代码——子类复写
 protected @StatusBarUtils.FakeStatusBarCfg int fakeStatusBarCfg() {
        return StatusBarUtils.FakeStatusBarCfg.NEED_WHEN_LOST;
    }

//子类复写
 protected open fun statusBarDarkFont(): Boolean {
        return !NightModeUtils().isNight()
    }

相关文章

  • Android 三星 11 12 沉浸式状态栏有灰色蒙层问题。

    在三星的android 11 12中,设置沉浸式状态栏,虽然主屏沉入了状态栏,但是状态栏依然有个灰色蒙层盖在上面。...

  • Android状态栏总结

    参考:android沉浸式状态栏、fitsSystemWindows、标题栏折叠 android中的windowT...

  • AndroidView

    Android 沉浸式 (透明) 状态栏适配 Android 沉浸式状态栏仿淘宝、京东拖拽商品详情(可嵌套View...

  • 屏幕适配【刘海屏适配】

    Android官方9.0刘海屏适配策略 如果非全屏(有状态栏),则app不受刘海屏的影响,刘海屏的高就是状态栏的高...

  • 折叠屏手机是三星内折好还是华为外翻好?

    如果华为手机可以渡过芯片难关和解决产能问题,那中国折叠屏手机市场就没三星折叠屏手机什么事儿了,因为三星折叠屏手机是...

  • 沉浸式状态栏

    1、1218683832/ImmersionBar android 4.4以上沉浸式状态栏和沉浸式导航栏管理,适配...

  • Android折叠屏适配

    手机信息 品牌:OPPO型号:PEUM00Android版本:11ColorOS版本:V12 屏幕信息 完全展开时...

  • 屏幕适配-刘海屏适配

    Android官方9.0刘海屏适配策略 1.如果非全屏模式(有状态栏),则app不受刘海屏影响,刘海屏的高度就是状...

  • 安卓适配

    ------刘海屏------屏幕适配 | Android 刘海屏适配总结Android刘海屏适配方案Androi...

  • 华为折叠屏适配

    华为折叠屏适配方案:华为在大屏设备上有系统级别的支持方案,华为平行视界,能够支持折叠屏分屏显示 华为折叠屏分屏显示...

网友评论

      本文标题:Android中三星折叠屏在多窗口运行时侵入式状态栏的适配问题

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