Jetpack Compose 中适配不同的屏幕尺寸

本文介绍了Jetpack Compose中如何适配不同屏幕尺寸,包括窗口大小分类,如Compact、Medium和Expanded。文章讲解了如何使用WindowSizeClass进行动态布局调整,并提供了示例代码。还讨论了折叠屏、TwoPane、FlowLayout、BottomNavigation和NavigationRail在不同屏幕尺寸的应用,以及列表导航的适配策略。
摘要由CSDN通过智能技术生成

窗口大小分类

在这里插入图片描述

Compose 将 Android 设备的屏幕尺寸分为三类:

  • Compact: 小屏幕,一般就是手机设备,屏幕宽度 < 600dp
  • Medium:中等屏幕,大号的板砖手机如折叠屏或平板的竖屏,600dp < 屏幕宽度 < 840dp
  • Expanded:展开屏幕,平板或平板电脑等,屏幕宽度 > 840dp

在这里插入图片描述

它是以某个维度来划分的,如上图是以宽度作为划分点,当然也可以按照高度来作为划分点:

在这里插入图片描述

但由于垂直滚动的普遍存在,可用宽度通常比可用高度更重要;因此,宽度窗口大小类别很可能与应用的界面更相关。所以大部分开发者只需要根据宽度调整应用即可。

窗口大小类别不适用于“isTablet-type”逻辑,而是由应用可用的窗口大小决定(无论运行应用的设备是什么类型);这有两个重大影响:

  • 实体设备不能保证特定的窗口大小类别。应用可用的屏幕空间可能会与设备的屏幕尺寸不同,这有很多原因。在移动设备上,分屏模式可以在多个应用之间拆分屏幕。在 Chrome 操作系统中,Android 应用可以呈现在可任意调整大小的自由式窗口中。可折叠设备可以有两个大小不同的屏幕,分别可通过折叠或展开设备使用。

  • 窗口大小类别在应用的整个生命周期内可能会发生变化。当应用处于运行状态时,设备更改屏幕方向、进行多任务处理和折叠/展开可能会改变可用的屏幕空间量。因此,窗口大小类别是动态的,应用的界面应相应地调整。

基于 Compose 的应用可以通过 calculateWindowSizeClass() 函数来当前窗口的分类,它使用 material3-window-size-class 库计算 WindowSizeClass,需要添加依赖:

implementation "androidx.compose.material3:material3-window-size-class:1.0.0"

调用示例代码:

import androidx.activity.compose.setContent
import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass

class MyActivity : ComponentActivity() {
   
    override fun onCreate(savedInstanceState: Bundle?) {
   
        super.onCreate(savedInstanceState)
        setContent {
   
            // 计算Activity当前窗口的窗口大小类别
            // 如果窗口大小改变了,例如当设备旋转时,calculateSizeClass返回的值也会改变。
            val windowSizeClass = calculateWindowSizeClass(this)
            MyApp(windowSizeClass)
        }
    }
}

@Composable
fun MyApp(windowSizeClass: WindowSizeClass) {
   
    // 根据不同的窗口大小类别,进行不同的视图展示逻辑
    when(windowSizeClass.widthSizeClass) {
   
        WindowWidthSizeClass.Compact -> Text("当前是 Compact 屏幕")
        WindowWidthSizeClass.Medium -> Text("当前是 Medium 屏幕")
        WindowWidthSizeClass.Expanded -> Text("当前是 Expanded 屏幕")
    }
}

在非 Compose 的应用中,也可以判断窗口大小类别,但是要麻烦一点:

enum class WindowSizeClass {
    COMPACT, MEDIUM, EXPANDED }

class MainActivity : Activity() {
   
    override fun onCreate(savedInstanceState: Bundle?) {
   
        super.onCreate(savedInstanceState)

        // ...

        // Replace with a known container that you can safely add a
        // view to where it won't affect the layout and the view
        // won't be replaced.
        val container: ViewGroup = binding.container

        // Add a utility view to the container to hook into
        // View.onConfigurationChanged. This is required for all
        // activities, even those that don't handle configuration
        // changes. We also can't use Activity.onConfigurationChanged,
        // since there are situations where that won't be called when
        // the configuration changes. View.onConfigurationChanged is
        // called in those scenarios.
        container.addView(object : View(this) {
   
            override fun onConfigurationChanged(newConfig: Configuration?) {
   
                super.onConfigurationChanged(newConfig)
                computeWindowSizeClasses()
            }
        })

        computeWindowSizeClasses()
    }
    // 非 Compose 应用中的使用方法
    enum class WindowSize {
    COMPACT, MEDIUM, EXPANDED }
    private fun computeWindowSizeClasses() {
   
        val metrics = WindowMetricsCalculator.getOrCreate()
            .computeCurrentWindowMetrics(this)

        val widthDp = metrics.bounds.width() / Resources.getSystem().displayMetrics.density
        val widthWindowSizeClass = when {
   
            widthDp < 600f -> WindowSize.COMPACT
            widthDp < 840f 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

川峰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值