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()
    }
}

<think>嗯,用户想了解Android折叠屏设备的适配方案,尤其是兼容性最佳的做法。首先,我需要回忆一下Android官方文档中提到的相关内容,以及社区推荐的实践方法。记得折叠屏适配主要涉及到屏幕连续性、多窗口模式、铰链区域处理等。 首先,用户可能需要知道基本概念,比如屏幕连续性(continuation)和多窗口模式。折叠屏设备通常有两种形态:展开和折叠,应用需要适应不同的屏幕尺寸和比例。这时候,使用resizeableActivity属性是关键,确保应用能够灵活调整布局。同时,Jetpack WindowManager库应该被提到,因为它提供了检测屏幕状态变化的API,比如FoldingFeature。 然后,铰链区域的适配也很重要。应用需要避免在铰链处显示关键内容,或者利用铰链区域进行分屏显示。比如Surface Duo的双屏布局,可能需要将内容分布在两个屏幕上。这时候,检查FoldingFeatureorientation和occlusionType属性,判断铰链的位置和是否遮挡,从而调整UI布局。 另外,资源文件的管理也很重要。使用不同的布局文件适配不同尺寸,比如使用layout-w600dp或layout-sw600dp来为大屏幕设计布局。ConstraintLayout和FlexboxLayout可以帮助实现灵活的布局结构。同时,Compose的响应式设计也是一个趋势,通过测量可用空间动态调整组件排列。 兼容性方面,需要考虑新旧设备的兼容。使用WindowManager库的版本兼容功能,比如使用Jetpack库中的WindowInfoTracker来获取窗口信息,而不是直接依赖系统API。这样可以在不同版本的系统上保持一致性。另外,Activity Embedding功能可以在大屏幕上拆分Activity,提升多任务处理体验,但需要检查设备是否支持。 测试环节也不能忽视,使用官方模拟器或者Surface Duo模拟器进行多形态测试,验证布局切换是否流畅,数据是否保持。最后,参考官方示例和社区案例,比如Compose的Demo项目,学习最佳实践。 用户可能还关心具体的代码实现,比如如何监听屏幕状态变化,如何处理布局的动态调整。需要给出代码示例,比如在Activity中收集窗口信息,并根据折叠状态更新UI。同时,强调使用标准API和兼容库的重要性,以确保最佳的兼容性。 总结一下,适配的关键点包括:使用响应式布局、处理铰链区域、管理资源文件、兼容性处理以及充分测试。用户可能需要一个结构化的步骤指南,从基础配置到高级功能实现,逐步完成适配。此外,提供相关资源和示例链接能帮助用户更深入理解和实践。</think>### Android折叠屏适配方案及最佳兼容性实现方法 #### 一、基础适配原则 1. **声明屏幕连续性** 在`AndroidManifest.xml`中声明支持屏幕尺寸动态变化: ```xml <activity android:name=".MainActivity" android:resizeableActivity="true" /> ``` 支持`resizeableActivity`可确保应用在折叠/展开时自动调整布局[^1]。 2. **响应式布局设计** - 使用`ConstraintLayout`实现动态约束 - 通过`Jetpack WindowManager`库检测折叠状态: ```kotlin implementation "androidx.window:window:1.1.0" ``` #### 二、铰链区域处理 ```kotlin val windowInfo = WindowInfoTracker.getOrCreate(this) windowInfo.windowLayoutInfo(this).collect { layoutInfo -> layoutInfo.displayFeatures.forEach { feature -> if (feature is FoldingFeature) { val foldBounds = feature.bounds when { feature.orientation == FoldingFeature.Orientation.HORIZONTAL -> updateHorizontalHinge(foldBounds) feature.orientation == FoldingFeature.Orientation.VERTICAL -> updateVerticalHinge(foldBounds) } } } } ``` 通过判断铰链方向(`orientation`)和遮挡类型(`occlusionType`)调整UI布局[^2]。 #### 三、多窗口模式适配 1. **分屏布局优化** ```xml <layout> <Switch android:layout_width="wrap_content" android:layout_height="wrap_content" android:checked="true" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </layout> ``` 使用`ConstraintLayout`百分比布局和`Guideline`实现动态对齐。 2. **Activity Embedding** ```kotlin val splitPair = SplitPairRule.Builder(...) .setClearTop(true) .build() SplitController.initialize(this, splitPair) ``` 支持多Activity同屏显示(需Android 12L+)[^2]。 #### 四、兼容性最佳实践 | 方案类型 | 实现方法 | 兼容范围 | |----------------|-----------------------------------|------------------| | 响应式布局 | ConstraintLayout+动态尺寸单位 | Android 4.2+ | | 铰链感知 | WindowManager+DisplayFeature | AndroidX兼容库 | | 多窗口支持 | Activity Embedding | Android 12L+ | #### 五、测试验证 1. 使用Android Studio折叠屏模拟器 2. 真机测试Surface Duo等设备 3. 验证布局切换时的数据保持: ```kotlin override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) // 处理配置变更 } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值