android 关于Jetpack Compose

6rqinv9w  于 2023-05-12  发布在  Android
关注(0)|答案(8)|浏览(202)

Jetpack Compose中是否有任何Orientation helper类,就像Flutter有https://flutter.dev/docs/cookbook/design/orientation一样??我需要知道方向何时改变,以便正确调整布局。

0lvr5msh

0lvr5msh1#

我们可以使用LocalConfiguration来监听方向的变化

@Composable
fun ConfigChangeExample() {
    val configuration = LocalConfiguration.current
    when (configuration.orientation) {
        Configuration.ORIENTATION_LANDSCAPE -> {
            Text("Landscape")
        }
        else -> {
            Text("Portrait")
        }
    }
}

注意:这不会帮助监听配置更改,这只会帮助获取当前配置。

jdgnovmf

jdgnovmf2#

为了观察方向,我们可以创建一个快照流来观察方向的变化,该变化提供给您可以直接使用的状态变量。

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

nhn9ugyo3#

我们可以在jectpack compose中使用state,这样当状态改变时,一个composable可以重新组合自己。
使用state监听configuration change的示例如下:

@Composable
fun ShowConfig(config: String) {
   Text(text = "$config!")
}

保持config state处于活动状态:-

var state by mutableStateOf("Potrait")

然后监听activity中的配置更改,并在配置时通过如下值更新状态:-

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

每当配置字符串的状态改变时,Greeting可组合件观察配置字符串的状态,并重新组合。

yk9xbfzb

yk9xbfzb4#

您可以从BoxWithConstraints中获取,然后比较widthheight
简单的例子:

@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")
        }
    }
tv6aics1

tv6aics15#

这里有一个小助手,用于在切换到纵向模式时将撰写行交换为列。您可能需要为您的目的稍微调整一下。

@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) })
72qzrwbm

72qzrwbm6#

添加基于新androidx.compose.material3.windowsizeclass库的更新答案。
您现在可以使用WindowSizeClass来查询width和height类,而不是直接检测方向。此库专门用于构建自适应布局,并将在Activity的大小/方向更改时自动重新组合布局。
这个API提供了宽度和高度的粗略大小(COMPACTMEDIUMEXPANDING)。这使得处理诸如折叠和大屏幕显示器之类的设备变得容易。这也考虑到使用分屏(方向保持不变)的电话和其他无法通过简单方向检查处理的选项。
下面是我做的一个简单的例子:

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告诉我,大多数手机都是纵向的,我可以相应地更新我的UI。
这些相同的枚举也可用于活动的高度,但文档指出-
大多数应用程序可以通过只考虑宽度窗口大小类来构建响应式UI。
(So对我来说是真的(true for me)
请注意,这个库仍然是alpha版本,并且显式地标记为Experimental,因此它可能会更改。我只是想在这里添加这个任何人尝试材料3与喷气背包组成。
官方指南-https://developer.android.com/guide/topics/large-screens/support-different-screen-sizes#window_size_classes
示例实现可以在JetNews示例应用程序-https://github.com/android/compose-samples/tree/main/JetNews中找到。
文档-https://developer.android.com/reference/kotlin/androidx/compose/material3/windowsizeclass/package-summary
发行说明(在1.0.0-alpha 10中发布,当前版本-alpha 13)-https://developer.android.com/jetpack/androidx/releases/compose-material3#1.0.0-alpha10

kognpnkq

kognpnkq7#

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
            },
        )
    }
}
fae0ux8s

fae0ux8s8#

您可以使用此方法动态更改值:

@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 }

相关问题