1

我想支持手机、平板电脑、可折叠设备和电视等设备。下面的代码会为此目的工作吗?

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            val windowSize = rememberWindowSizeClass()
            when (windowSize.widthWindowSizeClass) {
                is WindowSizeClass.WindowType.COMPACT -> {
                    CompactActivityUi()
                    /*TODO(reason = "Ui for COMPACT window")*/
                }
                is WindowSizeClass.WindowType.MEDIUM -> {
                    /*TODO(reason = "Ui for Medium window")*/
                }
                else -> {
                    /*TODO(reason = "Ui for EXPANDED window")*/
                }
            }
        }
    }
}

@Composable
fun CompactActivityUi() {
    AppTheme {
        Surface(
            modifier = Modifier.fillMaxSize(),
            color = MaterialTheme.colorScheme.background
        ) {

        }
    }
}

data class WindowSizeClass(
    val widthWindowSizeClass: WindowType,
    val heightWindowSizeClass: WindowType,
    val widthWindowDpSize: Dp,
    val heightWindowDpSize: Dp
) {
    sealed class WindowType {
        object COMPACT : WindowType()
        object MEDIUM : WindowType()
        object EXPANDED : WindowType()
    }
}

@Composable
fun Activity.rememberWindowSizeClass(): WindowSizeClass {
    val configuration = LocalConfiguration.current
    val windowMetrics = remember(configuration) {
        WindowMetricsCalculator.getOrCreate()
            .computeCurrentWindowMetrics(activity = this)
    }
    val windowDpSize = with(LocalDensity.current) {
        windowMetrics.bounds.toComposeRect().size.toDpSize()
    }
    return WindowSizeClass(
        widthWindowSizeClass = when {
            windowDpSize.width < 0.dp -> throw IllegalArgumentException("Dp value cannot be negative")
            windowDpSize.width < 600.dp -> WindowSizeClass.WindowType.COMPACT
            windowDpSize.width < 840.dp -> WindowSizeClass.WindowType.MEDIUM
            else -> WindowSizeClass.WindowType.EXPANDED
        },
        heightWindowSizeClass = when {
            windowDpSize.height < 0.dp -> throw IllegalArgumentException("Dp value cannot be negative")
            windowDpSize.height < 480.dp -> WindowSizeClass.WindowType.COMPACT
            windowDpSize.height < 900.dp -> WindowSizeClass.WindowType.MEDIUM
            else -> WindowSizeClass.WindowType.EXPANDED
        },
        widthWindowDpSize = windowDpSize.width,
        heightWindowDpSize = windowDpSize.height
    )
}

@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
    CompactActivityUi()
}

官方文档

官方样品

官方视频

此代码是否适用于可折叠设备,特别是桌面姿势的可折叠设备?

是否建议在手机上使用 BottomNavigation,在平板电脑上使用 Nav Rail 以及 Navigation Drawer 或 TV

4

1 回答 1

1

您包含的代码将帮助您支持不同尺寸的设备,但它不会检测可折叠姿势。为此,您需要使用 Jetpack 窗口管理器库来访问FoldingFeature信息(API 参考)。

Jetcaster 官方 Compose 示例有一个如何检测桌面/书本模式的示例(MainActivityWindowInfoUtil),但同样重要的是要注意一些可折叠设备具有完全独立的屏幕(即使是平面的)。为了支持各种可折叠设备,我建议检查FoldingFeature.isSeparatingFoldingFeature.state.

有关可折叠支持的更多信息,您可以查看以下文档:

对于导航,我不熟悉电视指南,但对于其他设备,我认为建议取决于当前的窗口大小等级。BottomNavigation 最适合COMPACT宽度(大多数手机),而 NavigationRail 更适合宽度(平板电脑MEDIUMEXPANDED更大的可折叠设备)。

于 2022-03-04T15:28:24.767 回答