Jetpack Compose 介绍
Orientation on Jetpack Compose
Jetpack Compose 中是否有方向助手 class,就像 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")
}
}
}
注意:这不会帮助监听配置变化,这只会帮助获取当前配置。
我们可以在 jectpack compose 中使用 state,这样当状态改变时,可组合对象会重新组合自己。
使用state
收听configuration change
的例子如下:-
@Composable
fun ShowConfig(config: String) {
Text(text = "$config!")
}
在activity中保留一个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 可组合项就会观察配置字符串的状态。
为了观察方向,我们可以创建一个快照流来观察方向的变化,这些变化会输入到您可以直接使用的状态变量中。
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()
}
}
您可以从 BoxWithConstraints
获取并比较 宽度 与 高度 。
简单示例:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ShowScreenOrientation()
}
}
@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")
}
}
}
这里有一个小帮手,可以在转向 portrait-mode 时将撰写的行换成列。您可能需要根据自己的目的对其进行一些调整。
@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) })
添加基于新 androidx.compose.material3.windowsizeclass
库的更新答案。
您现在可以使用 WindowSizeClass
查询宽度和高度 类,而不是直接检测方向。该库专门用于构建自适应布局,并会在 activity 的 size/orientation 更改时自动重新组合布局。
此 API 为您提供宽度和高度的粗略尺寸 (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
告诉我大多数手机都是纵向的,我可以相应地更新我的 UI。
这些相同的枚举也可用于 activity 的高度,但文档说明 -
Most apps can build a responsive UI by considering only the width
window size class.
(到目前为止,对我来说是正确的)
请注意,此库仍处于 alpha 阶段并明确标记为实验性,因此它可能会发生变化。我只是想在这里为任何使用 Jetpack Compose 尝试 Material 3 的人添加这个。
可以在 JetNews 示例应用程序中找到示例实现 - https://github.com/android/compose-samples/tree/main/JetNews。
发行说明(在 1.0.0-alpha10 中发布,当前版本 - alpha13)- https://developer.android.com/jetpack/androidx/releases/compose-material3#1.0.0-alpha10
Jetpack Compose 中是否有方向助手 class,就像 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")
}
}
}
注意:这不会帮助监听配置变化,这只会帮助获取当前配置。
我们可以在 jectpack compose 中使用 state,这样当状态改变时,可组合对象会重新组合自己。
使用state
收听configuration change
的例子如下:-
@Composable
fun ShowConfig(config: String) {
Text(text = "$config!")
}
在activity中保留一个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 可组合项就会观察配置字符串的状态。
为了观察方向,我们可以创建一个快照流来观察方向的变化,这些变化会输入到您可以直接使用的状态变量中。
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()
}
}
您可以从 BoxWithConstraints
获取并比较 宽度 与 高度 。
简单示例:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ShowScreenOrientation()
}
}
@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")
}
}
}
这里有一个小帮手,可以在转向 portrait-mode 时将撰写的行换成列。您可能需要根据自己的目的对其进行一些调整。
@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) })
添加基于新 androidx.compose.material3.windowsizeclass
库的更新答案。
您现在可以使用 WindowSizeClass
查询宽度和高度 类,而不是直接检测方向。该库专门用于构建自适应布局,并会在 activity 的 size/orientation 更改时自动重新组合布局。
此 API 为您提供宽度和高度的粗略尺寸 (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
告诉我大多数手机都是纵向的,我可以相应地更新我的 UI。
这些相同的枚举也可用于 activity 的高度,但文档说明 -
Most apps can build a responsive UI by considering only the width window size class.
(到目前为止,对我来说是正确的)
请注意,此库仍处于 alpha 阶段并明确标记为实验性,因此它可能会发生变化。我只是想在这里为任何使用 Jetpack Compose 尝试 Material 3 的人添加这个。
可以在 JetNews 示例应用程序中找到示例实现 - https://github.com/android/compose-samples/tree/main/JetNews。
发行说明(在 1.0.0-alpha10 中发布,当前版本 - alpha13)- https://developer.android.com/jetpack/androidx/releases/compose-material3#1.0.0-alpha10