Compose 适配 - 折叠屏形态 FoldingFeature

一、概念

屏幕适配除了尺寸,现在还有形态。

二、基本使用

2.1 获取 FoldingFeature

WindowInfoTracker 会公开窗口布局信息,通过 WindowInfoTracker.getOrCreater() 创建,它的 windowLayoutInfo() 方法会返回一个 WindowLayoutInfo 类型的数据流,将可折叠设备的折叠状态告知你的应用。对于该数据流的处理,调用 collectAsState() 转为 Compose 状态使用,如果是直接收集流的场景,生命周期选择 STARTED。WindowManager 会以 DisplayFeature 类型的 List 形式提供显示窗口的功能,通过过滤获取其中有关折叠屏信息的 FoldingFeature。

val foldingFeature = WindowInfoTracker
        .getOrCreate(context)    //获取实例
        .windowLayoutInfo(context)    //返回数据流
        .collectAsState(null)    //转为Compose状态使用
        .value    //获取可观察容器中的值
        ?.displayFeatures    //获取提供显示窗口功能的列表
        ?.filterIsInstance<FoldingFeature>()    //获取其中有关折叠屏的信息
        ?.firstOrNull()

2.2 判断折叠信息

通过 FoldingFeature 的字段获取折叠信息,state 折叠状态,orientation 折叠方向,isSeparating 屏幕是否被分为两个显示区域,occlusionType 折叠处是否遮挡显示。

FoldingFeature

.State

折叠状态。

.FLAT

展开

.HALF_OPENED

半折叠

.Orientation

折叠处(铰链/折痕)方向。

.HORIZONTAL

横向(半折叠状态下,横向就是桌面模式)。

.VERTICAL

纵向(半折叠状态下,纵向就是图书模式)。

isSeparating()

屏幕是否被分为两个显示区域。

true

(半折叠或跨越双屏情况下,始终返回true)。

false

.occlusionType

折叠处是否遮挡显示。 

NONE

折叠处能显示内容,一般无需处理,除非影响阅读交互。

FULL

折叠处会遮挡内容,像双屏连接处就是,需要通过 bounds 来留白或偏移界面元素。

.bounds

折叠处矩形区域。

是一个 Rect 类型,该区域一般不方便交互,用于留白或偏移界面元素。

2.3 分类加载逻辑

对于 WindowSizeClasses 的 Medium 或 Expanded 需要进行折叠状态的判断,如果是展开状态直接沿用布局,如果是半折叠状态需要通过折叠边方向分别为桌面模式和图书模式进行布局设计。

@Composable
fun Demo(
    windowSizeClass: WindowSizeClass = currentWindowAdaptiveInfo().windowSizeClass
) {
    //根据判断结果,分别加载不同界面或对变量赋值,顺序必须从大到小
    if (windowSizeClass.isWidthAtLeastBreakpoint(WindowSizeClass.WIDTH_DP_EXPANDED_LOWER_BOUND)) {
        if (AppTheme.isTableTopPosture()) {
            DeskScreen()
        } else if (AppTheme.isBookPosture()) {
            BookScreen()
        } else {
            ExpandedScreen()
        }
    } else if (windowSizeClass.isWidthAtLeastBreakpoint(WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND)) {
        //同上
    } else {
        CompactScreen()
    }
}

三、封装进自定义主题

//通过全局入口AppTheme获取更符合直觉,因此设为private
private val LocalFoldingFeature = compositionLocalOf<FoldingFeature?> { null }

object AppTheme {
    //用于获取折叠屏信息
    val foldFeature: FoldingFeature?
        @Composable get() = LocalFoldingFeature.current
    /**
     * 判断折叠屏是不是桌面模式
     */
    @Composable
    fun isTableTopPosture() : Boolean {
        val foldFeature = LocalFoldingFeature.current
        return foldFeature?.state == FoldingFeature.State.HALF_OPENED &&
                foldFeature.orientation == FoldingFeature.Orientation.HORIZONTAL
    }
    /**
     * 判断折叠屏是不是图书模式
     */
    @Composable
    fun isBookPosture() : Boolean {
        val foldFeature = LocalFoldingFeature.current
        return foldFeature?.state == FoldingFeature.State.HALF_OPENED &&
                foldFeature.orientation == FoldingFeature.Orientation.VERTICAL
    }
}

@Composable
fun AppTheme(
    content: @Composable () -> Unit
) {
    val context = LocalContext.current
    val foldingFeature = WindowInfoTracker
            .getOrCreate(context)
            .windowLayoutInfo(context)
            .collectAsState(null)
            .value
            ?.displayFeatures
            ?.filterIsInstance<FoldingFeature>()
            ?.firstOrNull()
    CompositionLocalProvider(
        LocalFoldingFeature provides foldingFeature
    ){
        content()
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值