Compose 适配 - 折叠屏形态 FoldingFeature

张开发
2026/4/21 9:18:25 15 分钟阅读

分享文章

Compose 适配 - 折叠屏形态 FoldingFeature
一、概念屏幕适配除了尺寸现在还有形态姿态。APP可用宽度展示内容窗格数常见形态Compact1或2推荐竖屏展开、竖屏半折叠书本模式、纵向二分屏。Medium2横屏展开、横屏半折叠翻盖模式。Expanded3横向二分屏。二、基本使用2.1 获取 FoldingFeatureWindowInfoTracker 会公开窗口布局信息通过 WindowInfoTracker.getOrCreater() 创建它的 windowLayoutInfo() 方法会返回一个 WindowLayoutInfo 类型的数据流将可折叠设备的折叠状态告知你的应用。对于该数据流的处理调用 collectAsState() 转为 Compose 状态使用如果是直接收集流的场景生命周期选择 STARTED。WindowManager 会以 DisplayFeature 类型的 List 形式提供显示窗口的功能通过过滤获取其中有关折叠屏信息的 FoldingFeature。val foldingFeature WindowInfoTracker .getOrCreate(context) //获取实例 .windowLayoutInfo(context) //返回数据流 .collectAsState(null) //转为Compose状态使用 .value //获取可观察容器中的值 ?.displayFeatures //获取提供显示窗口功能的列表 ?.filterIsInstanceFoldingFeature() //获取其中有关折叠屏的信息 ?.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 compositionLocalOfFoldingFeature? { 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 ?.filterIsInstanceFoldingFeature() ?.firstOrNull() CompositionLocalProvider( LocalFoldingFeature provides foldingFeature ){ content() } }

更多文章