我有一个观点,我想在一个16x9的比例.

在肖像中,它看起来很好:

enter image description here

在横向中,它使用了错误的高度,因此文本没有居中:

enter image description here

(您可以滚动到查看视图的其余部分:

enter image description here)

要复制的代码是:

/**
 * Portrait: width=375.6dp height=211.4dp
 * Landscape: expecting height=375.6dp but get height=443.1dp (a height that is taller than the screen is wide, not constrained?)
 */
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            RotationHeightDemoTheme {
//                Column(modifier = Modifier.verticalScroll(rememberScrollState())) { // swapping out LazyColumn to Column with verticalScroll still gives the same issue
                LazyColumn {
                    item {
                        BoxWithConstraints(
                            modifier = Modifier
                                .aspectRatio(16f / 9f, matchHeightConstraintsFirst = true)
                                // .fillParentMaxSize() // Using this "fixes" the issue in landscape but breaks portrait
                                .background(Color.Red),
                            contentAlignment = Alignment.Center,
                        ) {
                            Text(text = "BOX $maxWidth / $maxHeight")
                        }
                    }
                }
            }
        }
    }
}

comments .fillParentMaxSize个"修复"景观:

enter image description here

但却打破了肖像:

enter image description here

我需要保留LazyColumn,因为在肖像中,其他视图可能会出现在屏幕上,而在风景中是看不见的.

为什么在风景中BoxWith约束有错误的高度尺寸?

推荐答案

这个问题源于这样一个事实,即在列的内容lambda中,由项接收的约束具有无限的高度值,因为内容可以任意垂直滚动.

您可以获取容器的真实大小并将其存储在某个地方. 然后,您可以使用此值传递到组件的最大宽度/大小约束中,这样它就永远不会超过这些限制.之后,您可以应用aspectRation修改器. 在代码中:

var layoutSize: IntSize by remember { mutableStateOf(IntSize(0, 0)) }
Column(
  modifier = Modifier
      .fillMaxSize() // Ensure that your container takes up all the space it can so that we get the right size value here
      .onSizeChanged { intSize -> // *Very* important that this happens before `verticalScroll` is applied
          layoutSize = intSize // Store the real value before the vertical contraints go infinite when we make it scrollable
      }
      .verticalScroll(rememberScrollState()),
) {
  val density = LocalDensity.current
  BoxWithConstraints(
    modifier = Modifier
      .sizeIn(maxWidth = with(density) { layoutSize.width.toDp() }, maxHeight = with(density) { layoutSize.height.toDp() })
      .aspectRatio(16f / 9f, matchHeightConstraintsFirst = true)
      .background(Color.Red),
  ) {
    Text(text = "BOX $maxWidth / $maxHeight")
  }
}

这将给子项正确的max约束,然后一切都很顺利,它下的任何修改器都将在正确的max约束下操作,aspectRatio包含在您的 case 中.

这里需要注意的一件事是,在第一帧中,layoutSize的默认大小为0,0mutableStateOf内部的任何大小.因此,这可能看起来有点discord,取决于你的场景.但是,当layoutSize为默认情况时,您可以做一些不显示内容的事情,

Android相关问答推荐

未解析的引用:背景 colored颜色

derivedStateOf与使用key和MutableState记住

如何检测HitTest是否命中给定的网格对象?

两首合成曲的喷气背包动画

如何将Unicode符号作为文本居中放置在布局中的按钮(Android XML)中?

如何在Jetpack Compose中更新异步回调的用户界面

如何从LazyColumn中的图标异步获取可绘制的加载?

在androidStudio中,如何使用带有ResolutionStrategy的ResolutionSelector而不是setTargetResolve()?

弹出导航堆栈后,Compose 无法访问 Hilt View Model

Jetpack Compose 使用 SavedStateHandle 发送返回结果不适用于 ViewModel 中注入的 SavedStateHandle

了解 CoroutineScope(Job() + Dispatchers.Main) 语法

当父布局的背景为浅色时,Android ProgressBar 背景 colored颜色 变为灰色

任务 ':app:kaptGenerateStubsDebugKotlin' 执行失败

列表更改时,RecyclerView 中的列表不会更新

如何处理 com.google.gson.JsonSyntaxException: java.lang.NumberFormatException: For input string: "T1V 4Y8" Kotlin

更改 Android SDK 版本 33 后建议在 xml 布局文件中不起作用

从expose 的 dropdownMenu 可组合、jetpack 组合中 Select 选项时,不会触发文本字段的 onValueChange

如何在jetpack compose中创建自定义rememberState?

如何在 TextInputEdit 中调整可绘制对象的大小

Android 应用程序在启动时自动启动