语雀知识库地址:语雀HarmonyOS知识库
飞书知识库地址:飞书HarmonyOS知识库
本文示例代码地址:Gitee 仓库地址
嗨,大家好,我是小白
上篇文章向大家介绍了 ArkTS 中我们经常使用到的几种基础组件,Text、Button 等。但是这些基础组件并不能完全满足一个 APP 的布局管理
就好比我们在使用 APP 时,常常看到的商品列表、登陆界面、悬浮按钮等等,都是通过一系列的布局方式来呈现的
比如我们在使用购物软件查询商品时,展示出来的是一个列表布局;等应用的登录界面,用户名与输入框、用户名行与密码行属于一个不同方向的线性布局;又比如表格中的每一列宽度均匀分布,这又属于弹性布局
举一个栗子,假设我们要一个登录界面,该界面有用户名、密码及输入框,当我们不加任何容器的情况下,呈现出来的是下面这种效果
这样子我们的页面虽然有了元素,但是在整体布局上不是很合理,按理来说输入框应该是与文本同行展示,而现在缺是换行展示
这是因为当前没有给向同行的组件添加布局方式而导致的这种效果
这篇文章就来探讨一下常用的布局方式
线性布局——Column/Row
线性布局是应用中最常用的布局,通过线性容器 Row
和 Column
构建
线性布局是其他布局的基础,其子元素在水平方向和垂直方向依次排列
线性布局的排列方向由所选容器组件决定,Column 容器内子元素按照垂直方向排列,Row 容器内子元素按照水平方向排列。根据不同的排列方向,可选择使用 Row 或 Column 容器创建线性布局
基本概念
- 布局容器:具有布局能力的容器组件,可以承载其他元素作为其子元素,布局容器会对其子元素进行尺寸计算和布局排列
- 布局子元素:布局容器内部的元素
- 主轴:线性布局容器在布局方向上的轴线,子元素默认沿主轴排列。Row容器主轴为横向,Column容器主轴为纵向
- 交叉轴:垂直于主轴方向的轴线。Row容器交叉轴为纵向,Column容器交叉轴为横向
- 间距:布局子元素的间距
定义方式
Column(value?: {space?: string | number})
Row(value?:{space?: number | string })
参数解读
- space:横向或者竖向元素间距
Column({ space: 10 })
Row({ space: 10 })
设置属性
Column({ space: 10 })
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Center)
Row({ space: 10 })
.alignItems(VerticalAlign.Center)
.justifyContent(FlexAlign.Center)
- alignItems:
- Column 设置子组件在水平方向上的对齐格式
- Row 设置子组件在垂直方向上的对齐格式
- justifyContent:
- Column 设置子组件在垂直方向上的对齐格式
- Row 设置子组件在水平方向上的对齐格式
子元素在交叉轴上的对齐方式
交叉轴为垂直方向时,取值为VerticalAlign类型,水平方向取值为HorizontalAlign
alignSelf 属性用于控制单个子元素在容器交叉轴上的对齐方式,其优先级高于 alignItems 属性,如果设置了 alignSelf 属性,则在单个子元素上会覆盖 alignItems 属性
- Column
- HorizontalAlign.Start:子元素在水平方向左对齐
- HorizontalAlign.Center:子元素在水平方向居中对齐
- HorizontalAlign.End:子元素在水平方向右对齐
- Row
- VerticalAlign.Top:子元素在垂直方向顶部对齐
- VerticalAlign.Center:子元素在垂直方向居中对齐
- VerticalAlign.Bottom:子元素在垂直方向底部对齐
子元素在主轴上的排列方式
- Column
- justifyContent(FlexAlign.Start):元素在垂直方向首端对齐,第一个元素与行首对齐,同时后续的元素与前一个对齐
- justifyContent(FlexAlign.Center):元素在垂直方向中心对齐,第一个元素与行首的距离与最后一个元素与行尾距离相同
- justifyContent(FlexAlign.End):元素在垂直方向尾部对齐,最后一个元素与行尾对齐,其他元素与后一个对齐
- justifyContent(FlexAlign.Spacebetween):垂直方向均匀分配元素,相邻元素之间距离相同。第一个元素与行首对齐,最后一个元素与行尾对齐
- justifyContent(FlexAlign.SpaceAround):垂直方向均匀分配元素,相邻元素之间距离相同。第一个元素到行首的距离和最后一个元素到行尾的距离是相邻元素之间距离的一半
- justifyContent(FlexAlign.SpaceEvenly):垂直方向均匀分配元素,相邻元素之间的距离、第一个元素与行首的间距、最后一个元素到行尾的间距都完全一样
- Row
- justifyContent(FlexAlign.Start):元素在水平方向方向首端对齐,第一个元素与行首对齐,同时后续的元素与前一个对齐
- justifyContent(FlexAlign.Center):元素在水平方向方向中心对齐,第一个元素与行首的距离与最后一个元素与行尾距离相同
- justifyContent(FlexAlign.End):元素在水平方向方向尾部对齐,最后一个元素与行尾对齐,其他元素与后一个对齐
- justifyContent(FlexAlign.Spacebetween):水平方向方向均匀分配元素,相邻元素之间距离相同。第一个元素与行首对齐,最后一个元素与行尾对齐
- justifyContent(FlexAlign.SpaceAround):水平方向方向均匀分配元素,相邻元素之间距离相同。第一个元素到行首的距离和最后一个元素到行尾的距离是相邻元素之间距离的一半
- justifyContent(FlexAlign.SpaceEvenly):水平方向方向均匀分配元素,相邻元素之间的距离、第一个元素与行首的间距、最后一个元素到行尾的间距都完全一样
自适应拉伸
在线性布局下,常用空白填充组件Blank,在容器主轴方向自动填充空白空间,达到自适应拉伸效果
Row和Column作为容器,只需要添加宽高为百分比,当屏幕宽高发生变化时,会产生自适应效果
自适应缩放
自适应缩放是指子组件随容器尺寸的变化而按照预设的比例自动调整尺寸,适应各种不同大小的设备。在线性布局中,可以使用以下两种方法实现自适应缩放。
- 父容器尺寸确定时,使用 layoutWeight 属性设置子组件和兄弟元素在主轴上的权重,忽略元素本身尺寸设置,使它们在任意尺寸的设备下自适应占满剩余空间
- 父容器尺寸确定时,使用百分比设置子组件和兄弟元素的宽度,使他们在任意尺寸的设备下保持固定的自适应占比
自适应延伸
自适应延伸是指在不同尺寸设备下,当页面的内容超出屏幕大小而无法完全显示时,可以通过滚动条进行拖动展示。这种方法适用于线性布局中内容无法一屏展示的场景。通常有以下两种实现方式
- 在List中添加滚动条:当 List 子项过多一屏放不下时,可以将每一项子元素放置在不同的组件中,通过滚动条进行拖动展示。可以通过 scrollBar 属性设置滚动条的常驻状态,edgeEffect 属性设置拖动到内容最末端的回弹效果
- 使用Scroll组件:在线性布局中,可以进行竖向或者横向的布局。当一屏无法完全显示时,可以在Column或Row组件的外层包裹一个可滚动的容器组件Scroll来实现可滑动的线性布局
列表——List
基本概念
列表是一种复杂的容器,当列表项达到一定数量,内容超过屏幕大小时,可以自动提供滚动功能。它适合用于呈现同类数据类型或数据类型集,例如图片和文本。在列表中显示数据集合是许多应用程序中的常见要求(如通讯录、音乐列表、购物清单等)
使用列表可以轻松高效地显示结构化、可滚动的信息。通过在 List 组件中按垂直或者水平方向线性排列子组件 ListItemGroup 或 ListItem ,为列表中的行或列提供单个视图,或使用 ForEach 迭代一组行或列,或混合任意数量的单个视图和 ForEach 结构,构建一个列表。List 组件支持使用条件渲染、循环渲染、懒加载等渲染控制方式生成子组件
定义方式
List(value?: {space?: number | string, initialIndex?: number, scroller?: Scroller})
参数解读
List({ space: 20, initialIndex: 0 })
- space:子组件主轴方向的间隔
- initialIndex:设置当前List初次加载时视口起始位置显示的item的索引值
- scroller:可滚动组件的控制器,用于与可滚动组件进行绑定
设置属性
List({ space: 20, initialIndex: 0 }) {
ForEach(this.arr, (item) => {
ListItem() {
Text('' + item)
.width('100%')
.height(100)
.fontSize(16)
.textAlign(TextAlign.Center)
.borderRadius(10)
.backgroundColor(0xFFFFFF)
}
}, item => item)
}
.listDirection(Axis.Vertical) // 排列方向
.divider({ strokeWidth: 2, color: 0xFFFFFF, startMargin: 20, endMargin: 20 }) // 每行之间的分界线
.edgeEffect(EdgeEffect.Spring) // 滑动到边缘无效果
.onScrollIndex((firstIndex: number, lastIndex: number) => {
console.info('first' + firstIndex)
console.info('last' + lastIndex)
})
.width('90%')
.height('100%')
}
其中:
- listDirection:设置List组件排列方向
- divider:设置ListItem分割线样式,默认无分割线
- strokeWidth: 分割线的线宽
- color: 分割线的颜色
- startMargin: 分割线与列表侧边起始端的距离
- endMargin: 分割线与列表侧边结束端的距离
- edgeEffect:设置组件的滑动效果
- scrollBar:设置滚动条状态
设置事件
List 组件的相关事件参考官方文档
弹性布局——Flex
基本概念
弹性布局提供更加有效的方式对容器中的子元素进行排列、对齐和分配剩余空间
容器默认存在主轴与交叉轴,子元素默认沿主轴排列,子元素在主轴方向的尺寸称为主轴尺寸,在交叉轴方向的尺寸称为交叉轴尺寸
弹性布局在开发场景中用例特别多,比如页面头部导航栏的均匀分布、页面框架的搭建、多行数据的排列等等
定义方式
Flex(value?: { direction?: FlexDirection, wrap?: FlexWrap, justifyContent?: FlexAlign, alignItems?: ItemAlign, alignContent?: FlexAlign })
参数解读
Flex({
direction: FlexDirection.Row,
wrap: FlexWrap.NoWrap,
justifyContent: FlexAlign.Center,
alignItems: ItemAlign.Center,
alignContent: FlexAlign.Center
})
- direction:子组件在Flex容器上排列的方向,即主轴的方向
- wrap:Flex容器是单行/列还是多行/列排列
- justifyContent:所有子组件在Flex容器主轴上的对齐格式
- alignItems:所有子组件在Flex容器交叉轴上的对齐格式
- alignContent:交叉轴中有额外的空间时,多行内容的对齐方式。仅在wrap为Wrap或WrapReverse下生效
交叉轴对齐方式
容器组件的交叉轴对齐方式
通过Flex组件的alignItems参数设置子组件在交叉轴的对齐方式
- ItemAlign.Auto:使用Flex容器中默认配置
- ItemAlign.Start:交叉轴方向首部对齐
- ItemAlign.Center:交叉轴方向居中对齐
- ItemAlign.End:交叉轴方向底部对齐
- ItemAlign.Stretch:交叉轴方向拉伸填充,在未设置尺寸时,拉伸到容器尺寸
- ItemAlign. Baseline:交叉轴方向文本基线对齐
子组件设置交叉轴对齐
子组件的 alignSelf 属性也可以设置子组件在父容器交叉轴的对齐格式,且会覆盖 Flex 布局容器中 alignItems 配置
自适应拉伸
在弹性布局父组件尺寸不够大的时候,通过子组件的下面几个属性设置其在父容器的占比,达到自适应布局能力
- flexBasis:设置子组件在父容器主轴方向上的基准尺寸。如果设置了该值,则子项占用的空间为设置的值;如果没设置该属性,那子项的空间为 width / height 的值
- flexGrow:设置父容器的剩余空间分配给此属性所在组件的比例。用于“瓜分”父组件的剩余空间
- flexShrink: 当父容器空间不足时,子组件的压缩比例
层叠布局——Stack
基本概念
层叠布局用于在屏幕上预留一块区域来显示组件中的元素,提供元素可以重叠的布局。层叠布局通过Stack容器组件实现位置的固定定位与层叠,容器中的子组件依次入栈,后一个子元素覆盖前一个子元素,子元素可以叠加,也可以设置位置
层叠布局具有较强的页面层叠、位置定位能力,其使用场景有广告、卡片层叠效果等
定义方式
Stack(value?: { alignContent?: Alignment })
参数解读
Stack({ alignContent: Alignment.Center })
- alignContent:设置子组件在容器内的对齐方式
设置属性
Stack({ alignContent: Alignment.Center })
.alignContent(Alignment.Center)
- alignContent:设置所有子组件在容器内的对齐方式
Z 序控制
Stack容器中兄弟组件显示层级关系可以通过 Z序控制的 zIndex 属性改变。zIndex 值越大,显示层级越高,即 zIndex 值大的组件会覆盖在 zIndex 值小的组件上方
Stack({ alignContent: Alignment.BottomStart }) {
Column() {
Text('Stack子元素1').fontSize(15)
}.width(50).height(50).backgroundColor(0xffd306).zIndex(2)
Column() {
Text('Stack子元素2').fontSize(12)
}.width(75).height(75).backgroundColor(Color.Pink).zIndex(1)
Column() {
Text('Stack子元素3').fontSize(15)
}.width(100).height(100).backgroundColor(Color.Grey)
}.margin({ top: 10 }).width(125).height(125).backgroundColor(0xe0e0e0)