使用 Flexbox 进行布局
组件可以使用 Flexbox 算法来指定其子元素的布局。Flexbox 旨在在不同屏幕尺寸上提供一致的布局。
通常你会结合使用 flexDirection、alignItems 和 justifyContent 来实现合适的布局。
Flexbox 在 React Native 中的工作方式与它在 Web 的 CSS 中相同,但有少数例外。
默认值不同:flexDirection 默认为 column 而不是 row,alignContent 默认为 flex-start 而不是 stretch,flexShrink 默认为 0 而不是 1,flex 参数只支持单个数字。
Flex
flex 将定义你的元素如何沿主轴 “填充” 可用空间。空间会根据每个元素的 flex 属性进行分配。
在下面的示例中,红色、橙色和绿色视图都是容器视图中的子元素,且该容器设置了 flex: 1。红色视图使用 flex: 1,橙色视图使用 flex: 2,绿色视图使用 flex: 3。1+2+3 = 6,这意味着红色视图将获得 1/6 的空间,橙色视图获得 2/6 的空间,绿色视图获得 3/6 的空间。
Flex Direction
flexDirection 控制节点的子元素布局方向。这也称为主轴。交叉轴是与主轴垂直的轴,或者说是换行线所在的轴。
-
column(默认值)将子元素从上到下排列。如果启用了换行,则下一行将从容器顶部第一个元素的右侧开始。 -
row将子元素从左到右排列。如果启用了换行,则下一行将从容器左侧第一个元素的下方开始。 -
column-reverse将子元素从下到上排列。如果启用了换行,则下一行将从容器底部第一个元素的右侧开始。 -
row-reverse将子元素从右到左排列。如果启用了换行,则下一行将从容器右侧第一个元素的下方开始。
你可以在这里了解更多。
- TypeScript
- JavaScript
布局方向
布局 direction 指定层级结构中子元素和文本的布局方向。布局方向也会影响 start 和 end 分别指向哪一侧。默认情况下,React Native 使用 LTR 布局方向进行布局。在这种模式下,start 指向左侧,end 指向右侧。
-
LTR(默认值)文本和子元素从左到右排列。应用于元素起始端的外边距和内边距会应用在左侧。 -
RTL文本和子元素从右到左排列。应用于元素起始端的外边距和内边距会应用在右侧。
- TypeScript
- JavaScript
对齐内容
justifyContent 描述了如何在容器的主轴上对齐子元素。例如,当容器的 flexDirection 设置为 row 时,你可以使用这个属性让子元素在容器中水平居中;当 flexDirection 设置为 column 时,则可以让子元素在容器中垂直居中。
-
flex-start(默认值)将容器的子元素对齐到容器主轴的起始位置。 -
flex-end将容器的子元素对齐到容器主轴的末尾位置。 -
center将容器的子元素对齐到容器主轴的中心位置。 -
space-between在容器主轴上均匀分布子元素,将剩余空间分配在子元素之间。 -
space-around在容器主轴上均匀分布子元素,将剩余空间分配在子元素周围。与space-between相比,使用space-around会使空间分布到第一个子元素的起始位置和最后一个子元素的末尾位置。 -
space-evenly沿主轴在对齐容器内均匀分布子元素。每一对相邻项之间的间距、主轴起始边缘与第一个项之间的间距,以及主轴末尾边缘与最后一个项之间的间距,完全相同。
你可以在这里了解更多。
- TypeScript
- JavaScript
对齐项目
alignItems 描述了如何沿容器的交叉轴对齐子元素。它与 justifyContent 非常相似,但 justifyContent 作用于主轴,而 alignItems 作用于交叉轴。
-
stretch(默认值)将容器的子元素拉伸,以匹配容器交叉轴的height。 -
flex-start将容器的子元素对齐到容器交叉轴的起始位置。 -
flex-end将容器的子元素对齐到容器交叉轴的末尾位置。 -
center将容器的子元素对齐到容器交叉轴的中心位置。 -
baseline将容器的子元素沿共同的基线对齐。单个子元素可以被设置为其父元素的参考基线。
要让 stretch 生效,子元素在次轴上不能有固定尺寸。在下面的示例中,在移除子元素上的 width: 50 之前,设置 alignItems: stretch 不会产生任何效果。
你可以在这里了解更多。
- TypeScript
- JavaScript
自身对齐
alignSelf 与 alignItems 具有相同的选项和效果,但不同之处在于,它不是影响容器内的子项,而是可以将此属性应用于单个子项,以更改其在父容器中的对齐方式。alignSelf 会覆盖父级通过 alignItems 设置的任何选项。
- TypeScript
- JavaScript
对齐内容
alignContent 定义了沿交叉轴分布各行的方式。只有在使用 flexWrap 将项目换行到多行时才会生效。
-
flex-start(默认值) 将换行后的各行对齐到容器交叉轴的起始位置。 -
flex-end将换行后的各行对齐到容器交叉轴的末尾位置。 -
stretch(在 Web 上使用 Yoga 时的默认值) 拉伸换行后的各行,以匹配容器交叉轴的高度。 -
center将换行后的各行居中对齐于容器交叉轴。 -
space-between在容器交叉轴上均匀分布换行后的各行,并在各行之间分配剩余空间。 -
space-around在容器交叉轴上均匀分布换行后的各行,并在各行周围分配剩余空间。容器两端的空间大小是项目之间空间的一半。 -
space-evenly在容器交叉轴上均匀分布换行后的各行,并在各行周围分配剩余空间。每个间距大小都相同。
你可以在这里了解更多。
- TypeScript
- JavaScript
Flex Wrap
flexWrap 属性设置在容器上,用于控制当子元素在主轴方向上超出容器尺寸时会发生什么。默认情况下,子元素会被强制放在同一行中(这可能会让元素变小)。如果允许换行,项目会在需要时沿主轴换成多行。
在换行时,可以使用 alignContent 来指定这些行在容器中的排列方式。更多信息请见这里。
- TypeScript
- JavaScript
Flex Basis、Grow 和 Shrink
-
flexBasis是一种与轴无关的方式,用于提供沿主轴方向上项目的默认尺寸。为子元素设置flexBasis类似于:如果其父元素是flexDirection: row的容器,则设置该子元素的width;如果其父元素是flexDirection: column的容器,则设置该子元素的height。项目的flexBasis是该项目的默认尺寸,也就是在执行任何flexGrow和flexShrink计算之前的尺寸。 -
flexGrow描述容器中有多少剩余空间应沿主轴分配给其子元素。在布局完子元素后,容器会根据子元素指定的 flex grow 值分配任何剩余空间。flexGrow接受任何 >= 0 的浮点数,默认值为 0。容器会按子元素的flexGrow值加权,把任何剩余空间分配给它们。 -
flexShrink描述在子元素总尺寸沿主轴方向超过容器尺寸时,如何沿主轴方向缩小子元素。flexShrink与flexGrow非常相似,如果把任何溢出的尺寸视为负的剩余空间,它们的理解方式也可以相同。这两个属性也能很好地配合使用,让子元素按需伸缩。flexShrink接受任何 >= 0 的浮点数,默认值为 0(在 web 上默认值为 1)。容器会按子元素的flexShrink值加权,缩小其子元素。
你可以在这里了解更多信息。
- TypeScript
- JavaScript
行间距、列间距和间距
-
rowGap设置元素各行之间间隙(gutter)的大小。 -
columnGap设置元素各列之间间隙(gutter)的大小。 -
gap设置行与列之间间隙(gutter)的大小。它是rowGap和columnGap的简写。
你可以将 flexWrap 和 alignContent 与 gap 一起使用,以在项目之间添加一致的间距。
- TypeScript
- JavaScript
宽度和高度
width 属性指定元素内容区域的宽度。类似地,height 属性指定元素内容区域的高度。
width 和 height 都可以采用以下值:
-
auto(默认值)React Native 会根据元素的内容来计算元素的宽/高,无论这些内容是其他子元素、文本还是图片。 -
pixels以绝对像素定义宽/高。根据组件上设置的其他样式,这可能是也可能不是该节点的最终尺寸。 -
percentage分别以其父级宽度或高度的百分比来定义宽度或高度。
- TypeScript
- JavaScript
定位
元素的 position 类型定义了它相对于自身、其父元素或其包含块的定位方式。
-
relative(默认值)默认情况下,元素采用相对定位。这意味着元素会先按照布局的正常流进行定位,然后再根据top、right、bottom和left的值,相对于该位置进行偏移。这个偏移不会影响任何兄弟元素或父元素的位置。 -
absolute当采用绝对定位时,元素不会参与正常的布局流,而是独立于其兄弟元素进行布局。其位置由top、right、bottom和left的值决定。这些值会将元素相对于其包含块进行定位。 -
static当采用静态定位时,元素会按照布局的正常流进行定位,并且会忽略top、right、bottom和left的值。此position还会导致该元素不会为绝对定位的后代形成包含块,除非存在某些其他优先级更高的样式属性(例如transform)。这使得absolute元素可以相对于不是其父元素的某个对象进行定位。请注意,static仅在 New Architecture 中可用。
- TypeScript
- JavaScript
包含块
元素的包含块是一个控制其位置和尺寸的祖先元素。 在 React Native 中,包含块的工作方式与 它们在 Web 上的工作方式非常相似,只是由于缺少某些 Web 特性而做了一些简化。
绝对定位元素的 top、right、bottom 和 left 值将相对于其包含块。
应用于绝对定位元素的百分比长度(例如:width: '50%' 或 padding: '10%')将相对于其包含块的尺寸进行计算。例如,如果包含块宽度为 100 个点,那么绝对定位元素上的 width: 50% 会使其宽度变为 50 个点。
下面的列表将帮助你确定任意给定元素的包含块:
- 如果该元素的
position类型是relative或static,那么它的包含块就是其父元素。 - 如果该元素的
position类型是absolute,那么它的包含块就是最近的祖先元素,并且满足以下任一条件:- 它的
position类型不是static - 它具有
transform
- 它的
深入了解
查看交互式的 yoga playground,你可以借助它更好地理解 flexbox。
我们已经介绍了基础知识,但布局中你可能还需要许多其他样式。控制布局的完整属性列表已在此处记录。
此外,你还可以查看来自 Wix Engineers 的一些示例。