原文链接。

MAD 技术:Compose 布局 和 修饰符 第 3 集

Jetpack Compose:约束 和 修饰符 顺序

在 上一篇 MAD 技术文章 中,您了解了将数据转换为 UI 的 Compose 的三个阶段。咱们创立了一个 思维模型 来协助咱们推理 app 的规划实现。在这一集中,咱们将运用该思维模型来学习推理 修饰符链 以及它是怎么影响咱们的可组合项的巨细的。

您也能够将本文作为 MAD 技术视频观看: youtu.be/OeC5jMV342A

还记得上一集咱们有 三个阶段 将数据转换为 UI 吗:

  1. 组合: 显现什么
  2. 布局: 放在哪儿
  3. 制作: 怎么渲染

修饰符能够影响不同的阶段。例如,sizepadding 修饰符在布局阶段影响可组合项的巨细和间距,而 clip 修饰符在制作阶段影响可组合项的形状:

Jetpack Compose:约束 和 修饰符 顺序

咱们还知道,咱们能够向可组合项增加多个修饰符,然后 创立一个链条。但是,这些链中的不同修饰符是怎么相互影响的,却并不总是清楚明了。

自己试试

让咱们从一些操练开端。对以下每个代码片段,请尝试找出 哪个选项将是履行该片段的成果,选项 A 或 B:

问题 1

/* Copyright 2023 Google LLC.
   SPDX-License-Identifier: Apache-2.0 */
Image(
  painterResource(R.drawable.frag), 
  contentDescription = null,
  Modifier
    .fillMaxSize()
    .size(50.dp)
)

Jetpack Compose:约束 和 修饰符 顺序

问题 2

/* Copyright 2023 Google LLC.
   SPDX-License-Identifier: Apache-2.0 */
Image(
  painterResource(R.drawable.frag), 
  contentDescription = null,
  Modifier
    .fillMaxSize()
    .wrapContentSize()
    .size(50.dp)
)

Jetpack Compose:约束 和 修饰符 顺序

问题 3

/* Copyright 2023 Google LLC.
   SPDX-License-Identifier: Apache-2.0 */
Image(
  painterResource(R.drawable.frag), 
  contentDescription = null,
  Modifier
    .clip(CircleShape)
    .padding(10.dp)
    .size(100.dp)
)

Jetpack Compose:约束 和 修饰符 顺序

不能确认答案?那你来对地方了!持续阅读来了解更多信息。(往这儿看,答案就在博文结尾)

束缚

要了解怎么推理修饰符次序,咱们有必要了解布局阶段 Constraints的效果。

还记得吗,在上一篇文章中咱们讨论了布局阶段怎么遵从 三步算法 找到每个布局节点的宽度、高度和 x、y 坐标:

  1. 量子节点: 一个节点丈量它的子节点,假如有的话。
  2. 决议本身巨细: 基于这些丈量,节点将决议本身巨细。
  3. 放置子节点: 每个子节点都相对于节点本身的方位放置。

在此算法的前两个步骤中,束缚有助于 为咱们的节点找到合适的巨细。它们是节点宽度和高度的 最小和最大鸿沟。当节点决议它的巨细时,它的丈量巨细应该落在这个给定的巨细范围内。

在算法的第一步中,束缚在 UI 树中 从父级传递给子级。当父节点丈量其子节点时,它会向每个子节点供给这些束缚,让他们知道答应的巨细。然后,当它决议自己的巨细时,它也会恪守由自己的父级们传入的束缚。

束缚的类型

束缚能够是 有界的,表明最小和最大的宽度和高度:

Jetpack Compose:约束 和 修饰符 顺序

有界的束缚

束缚也能够是 无界的,在这种情况下节点不受任何巨细的束缚。 然后将最大的宽度和高度鸿沟设置为无穷大:

Jetpack Compose:约束 和 修饰符 顺序

无界的束缚

又或许束缚也能够是 准确的,要求节点遵从准确的巨细要求。最小和最大的鸿沟设置为相同的值:

Jetpack Compose:约束 和 修饰符 顺序

准确的束缚

当然,这些的组合也是有用的,例如限制宽度,同时答应无限制的最大高度,或许设置准确宽度但供给有界高度:

Jetpack Compose:约束 和 修饰符 顺序

有界的、无界的 和 准确的 宽度和高度的组合

演练算法

要了解束缚怎么从父级传递给子级,以及怎么依据这些束缚解析巨细,最好 看一个例子。不管怎样,这在视频格式中都更简单出现,所以我建议您 观看 MAD 技术视频的“示例”一章

youtu.be/OeC5jMV342A

修饰符及其对束缚的影响

经过观看视频,您应该很好地了解 束缚怎么影响可组合项的巨细,以及 修饰符怎么影响这些束缚。 在本节中,咱们将仔细研讨一些特定的修饰符以及它们是怎么影响束缚的。

size修饰符

让咱们看看下面的 UI 树,它应该在 300dp 乘 200dp 的容器中出现。束缚是 有界的,答应宽度在 100dp300dp 之间,高度在 100dp200dp 之间。

Jetpack Compose:约束 和 修饰符 顺序

size 修饰符 调整传入的束缚以匹配传递给它的值,例如 150dp

Jetpack Compose:约束 和 修饰符 顺序

但是,假如 恳求的尺度太小或太大 怎么办?也就是说,假如宽度和高度小于最小束缚鸿沟,或许大于最大束缚鸿沟怎么办?

Jetpack Compose:约束 和 修饰符 顺序

在这种情况下,修饰符将尝试 尽可能挨近地匹配传递的束缚,同时仍然恪守传入的束缚:

Jetpack Compose:约束 和 修饰符 顺序

这也解说了为什么 链接多个size修饰符不起效果。 第一个 size 修饰符会将最小和最大束缚设置为固定值,即便第二个 size 修饰符恳求更小或更大的巨细,它仍然需求恪守传入的确切鸿沟,因而它不会掩盖这些值:

Jetpack Compose:约束 和 修饰符 顺序

requiredSize 修饰符

假如您的确需求您的节点 掩盖传入的束缚,您能够将 size 修饰符替换为另一个名为 requiredSize 的修饰符。 它将替换传入的束缚并传递您指定的巨细,作为准确鸿沟。 然后,当巨细被传递回树时,子节点将在可用空间中居中:

Jetpack Compose:约束 和 修饰符 顺序

width 和 height 修饰符

在前面的示例中,咱们运用了 size 修饰符,它能够习惯束缚的宽度和高度。但是,咱们也能够将它们替换为 width 修饰符,设置一个 固定的宽度,但保存不决的高度。或许咱们能够运用 height 修饰符,它设置了一个 固定的高度,但保存不决的宽度

Jetpack Compose:约束 和 修饰符 顺序

sizeIn 修饰符

假如您需求对束缚进行细粒度控制,并希望 依据您的详细需求调整它们,您能够运用 sizeIn 修饰符:

Jetpack Compose:约束 和 修饰符 顺序

操练的答案

已然咱们了解了束缚以及它们怎么影响丈量,那让咱们回到咱们开端的用例并找到正确的解决方案

问题 1

/* Copyright 2023 Google LLC.
   SPDX-License-Identifier: Apache-2.0 */
Image(
  painterResource(R.drawable.frag), 
  contentDescription = null,
  Modifier
    .fillMaxSize()
    .size(50.dp)
)

这是解决方案:

Jetpack Compose:约束 和 修饰符 顺序

  • fillMaxSize 修饰符更改束缚以将最小宽度和高度都设置为最大值 – 宽度为 300dp,高度为 200dp
  • 因而,即便 size 修饰符想要运用 50dp 的巨细,它仍然需求恪守传入的最小束缚。因而,巨细修饰符还将输出 300 乘以 200 的准确束缚鸿沟,有用地 疏忽 size 修饰符中供给的
  • Image 遵从这些鸿沟并(向上)陈述巨细为 300 乘以 200,这个巨细将一直向上传递。

问题 2

/* Copyright 2023 Google LLC.
   SPDX-License-Identifier: Apache-2.0 */
Image(
  painterResource(R.drawable.frag), 
  contentDescription = null,
  Modifier
    .fillMaxSize()
    .wrapContentSize()
    .size(50.dp)
)

这是解决方案:

Jetpack Compose:约束 和 修饰符 顺序

  • fillMaxSize 修饰符的行为仍然相同,并调整束缚以将最小宽度和高度都设置为最大值 – 宽度为 300dp,高度为 200dp
  • wrapContentSize 修饰符重置最小束缚。 因而,虽然 fillMaxSize 导致固定束缚,但 wrapContentSize 将其重置回有界束缚。下面的节点现在能够再次占据整个空间,或许小于整个空间。
  • size 修饰符将束缚设置为 50 的最小和最大边界。
  • Image 解析为 5050 的巨细,并且 size 修饰符将其转发。
  • wrapContentSize 修饰符有一个特殊的属性。它承受它的子项,并 将它放在 传递给它的 可用最小鸿沟的中心。因而,它与父级通信的巨细等于传递给它的最小边界。

经过组合仅仅三个修饰符,咱们就能够为咱们的可组合项界说一个尺度,并将其居中于其父级!

问题 3

/* Copyright 2023 Google LLC.
   SPDX-License-Identifier: Apache-2.0 */
Image(
  painterResource(R.drawable.frag), 
  contentDescription = null,
  Modifier
    .clip(CircleShape)
    .padding(10.dp)
    .size(100.dp)
)

这是解决方案:

Jetpack Compose:约束 和 修饰符 顺序

  • clip 修饰符不会更改束缚。
  • padding 修饰符降低了最大束缚。
  • size 修饰符将所有束缚设置为 100dp
  • Image 恪守这些束缚并陈述巨细为 100 乘以 100dp
  • padding 修饰符在所有尺度上增加 10dp,因而它会将陈述的宽度和高度增加 20dp
  • 现在,在制作阶段,clip 修饰符效果于 120120dp 的画布。因而它 创立了一个该巨细的圆形蒙版。
  • padding 修饰符然后在所有尺度上以 10dp 刺进其内容,因而它把画布尺度降低到了100100dp
  • 然后在该画布中制作 Image。你能够看到图像是依据本来的 120dp 圆进行裁剪的,因而咱们看到了非圆的成果。

总结

哇,今天内容真不少!您了解了 束缚,并运用它们来推理修饰符、怎么对其进行排序以及丈量。

在下一篇文章中,咱们将向您展示怎么运用这些信息来开端实现 您自己的自界说布局

这篇博文是系列博文的一部分:

第 1 集:Compose 布局 和 修饰符 的基础知识
第 2 集:Compose 的各个阶段
第 3 集:束缚 和 修饰符 次序
第 4 集:高级布局概念