Jetpack Compose中是否有任何定向助手类,就像Flutter有的https://flutter.dev/docs/cookbook/design/orientation?我需要知道方向何时更改以正确调整我的布局。
Jetpack Compose中是否有任何定向助手类,就像Flutter有的https://flutter.dev/docs/cookbook/design/orientation?我需要知道方向何时更改以正确调整我的布局。
LocalConfiguration
来确定当前的方向是什么,但是下面的代码并不能帮助监听配置的变化:@Composable
fun ConfigChangeExample() {
val configuration = LocalConfiguration.current
when (configuration.orientation) {
Configuration.ORIENTATION_LANDSCAPE -> {
Text("Landscape")
}
else -> {
Text("Portrait")
}
}
}
var orientation by remember { mutableStateOf(Configuration.ORIENTATION_PORTRAIT) }
val configuration = LocalConfiguration.current
// If our configuration changes then this will launch a new coroutine scope for it
LaunchedEffect(configuration) {
// Save any changes to the orientation value on the configuration object
snapshotFlow { configuration.orientation }
.collect { orientation = it }
}
when (orientation) {
Configuration.ORIENTATION_LANDSCAPE -> {
LandscapeContent()
}
else -> {
PortraitContent()
}
}
@Composable
fun ShowConfig(config: String) {
Text(text = "$config!")
}
在活动中保留配置状态
:
var state by mutableStateOf("Potrait")
然后监听活动中的配置更改,当配置更改时,通过该值更新状态,例如:
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
state = "Landscape" // this will automatically change the text to landscape
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
state = "Potrait" // this will automatically change the text to potrait
}
}
BoxWithConstraints
中获取它,并比较 宽度 和 高度。 @Composable
fun ShowScreenOrientation() {
BoxWithConstraints {
val mode = remember { mutableStateOf("") }
mode.value = if (maxWidth < maxHeight) "Portrait" else "Landscape"
Text(text = "Now it is in ${mode.value} mode")
}
}
androidx.compose.material3.windowsizeclass
库,更新答案。WindowSizeClass
查询宽度和高度类别,而不是直接检测方向。该库专门用于构建自适应布局,并在活动大小/方向更改时自动重新组合布局。COMPACT
,MEDIUM
,EXPANDING
),这使得处理可折叠设备和大屏幕显示器变得容易。这还考虑了使用分屏的手机(方向保持不变)和其他无法通过简单的方向检查处理的选项。class MainActivity {
/* ...... */
setContent {
val windowSizeClass = calculateWindowSizeClass(this)
/* .... */
MyApp(windowWidthSizeClass = windowSizeClass.widthSizeClass, /* .... */ )
}
}
@Composable
fun MyApp(windowWidthSizeClass: WindowWidthSizeClass, /* ... */) {
when(windowWidthSizeClass) {
WindowWidthSizeClass.Expanded -> // orientation is landscape in most devices including foldables (width 840dp+)
WindowWidthSizeClass.Medium -> // Most tablets are in landscape, larger unfolded inner displays in portrait (width 600dp+)
WindowWidthSizeClass.Compact -> // Most phones in portrait
}
}
windowWidthSizeClass
等于WindowWidthSizeClass.Expanded
时,我可以将布局设置为横向视图。我还可以使用WindowWidthSizeClass.Medium
来优化我的布局,以适应大型设备(如平板电脑和可折叠设备)。
最后,WindowWidthSizeClass.Compact
告诉我大多数移动设备都是纵向的,我可以相应地更新我的用户界面。@Composable
fun OrientationSwapper(
content1: @Composable (modifier: Modifier) -> Unit,
content2: @Composable (modifier: Modifier) -> Unit
) {
val portrait = LocalConfiguration.current.orientation == Configuration.ORIENTATION_PORTRAIT
if (portrait) {
Column(verticalArrangement = Arrangement.SpaceEvenly, modifier = Modifier.fillMaxSize()) {
content1(modifier = Modifier.weight(1f))
content2(modifier = Modifier.weight(1f))
}
} else {
Row(horizontalArrangement = Arrangement.SpaceEvenly, modifier = Modifier.fillMaxSize()) {
content1(modifier = Modifier.weight(1f))
content2(modifier = Modifier.weight(1f))
}
}
}
OrientationSwapper(
content1 = { modifier ->
Text("foo", modifier = modifier) },
content2 = { modifier ->
Text("bar", modifier = modifier) })
var orientation by remember { mutableStateOf(Configuration.ORIENTATION_PORTRAIT) }
LaunchedEffect(configuration) {
snapshotFlow { configuration.orientation }
.collect { orientation = it }
}
when (orientation) {
Configuration.ORIENTATION_LANDSCAPE -> {
LandScapeScreen(
isPortrait = false,
) {
activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
orientation = Configuration.ORIENTATION_PORTRAIT
}
}
else -> {
PortraitUI(
isPortrait = true,
onClick = {
activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
orientation = Configuration.ORIENTATION_LANDSCAPE
},
)
}
}
您可以使用此方法动态更改值:
@Composable
fun <T> dynamicOrientationValue(portraitValue: T, landscapeValue: T): T =
when (LocalConfiguration.current.orientation) {
Configuration.ORIENTATION_LANDSCAPE -> landscapeValue
else -> portraitValue
}
使用方法:
SpinBtn(
modifier = Modifier
.fillMaxWidth(dynamicOrientationValue(0.6f, 0.3f))
.align(dynamicOrientationValue(BottomCenter, CenterEnd))
.padding(32.dp), isSpinning = isSpinning
) { isSpinning = true }