今日核心:
1.弹性布局 Flex
2.定位
3.层叠布局
(注:找不到图片啦,所以只能图片自己放就好,命名遵循变量命名规则)
1. 弹性布局(Flex)
弹性布局(Flex)提供更加有效的方式对容器中的子元素进行排列、对齐和分配剩余空间。常用于页面头部导航栏的均匀分布、页面框架的搭建、多行数据的排列等。
容器默认存在主轴与交叉轴,子元素默认沿主轴排列,子元素在主轴方向的尺寸称为主轴尺寸,在交叉轴方向的尺寸称为交叉轴尺寸。
1.1. 基本使用
弹性容器组件: Flex() 基本使用
Flex(参数对象) {
子组件1
子组件2
子组件3
子组件N
}
示例代码
@Entry
@Component
struct Index {
build() {
Flex() {
Text('1')
.width('33%')
.height(30)
.backgroundColor(Color.Orange)
Text('2')
.width('33%')
.height(30)
.backgroundColor(Color.Pink)
Text('3')
.width('33%')
.height(30)
.backgroundColor(Color.Orange)
}
.width('100%')
.height(200)
.backgroundColor('#ccc')
}
}
1.2. 布局方向
在弹性布局中,容器的子元素可以按照任意方向排列(默认水平排列)。通过设置参数 direction,可以决定主轴的方向,从而控制子元素的排列方向
参数:direction
值:枚举 FlexDirection
示例代码
@Entry
@Component
struct Index {
build() {
// 垂直排列
Flex({direction: FlexDirection.Column }) {
Text('1')
.width('33%')
.height(30)
.backgroundColor(Color.Orange)
Text('2')
.width('33%')
.height(30)
.backgroundColor(Color.Pink)
Text('3')
.width('33%')
.height(30)
.backgroundColor(Color.Orange)
}
.width('100%')
.height(200)
.backgroundColor('#ccc')
}
}
1.3. 主轴对齐方式
参数:justifyContent
值:枚举 FlexAlign(属性与线性布局主轴对齐方式相同)
示例代码
@Entry
@Component
struct Index {
build() {
Flex({ justifyContent: FlexAlign.SpaceBetween }) {
Text('1')
.width(30)
.height(30)
.backgroundColor(Color.Orange)
Text('2')
.width(30)
.height(30)
.backgroundColor(Color.Pink)
Text('3')
.width(30)
.height(30)
.backgroundColor(Color.Orange)
Text('4')
.width(30)
.height(30)
.backgroundColor(Color.Pink)
}
.width('100%')
.height(100)
.backgroundColor('#ccc')
}
}
1.4. 交叉轴对齐方式
参数:alignItems
值:枚举 ItemAlign
示例代码
@Entry
@Component struct Index {
build() {
Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceBetween }) {
Text('1')
.width(30)
.height(30)
.backgroundColor(Color.Orange)
Text('2')
.width(30)
.height(30)
.backgroundColor(Color.Pink)
// 交叉轴拉伸
.alignSelf(ItemAlign.Stretch)
Text('3')
.width(30)
.height(30)
.backgroundColor(Color.Orange)
Text('4')
.width(30)
.height(30)
.backgroundColor(Color.Pink)
}
.width('100%')
.height(200)
.backgroundColor('#ccc')
}
}
1.5. 布局换行
弹性布局分为单行布局和多行布局。默认情况下,Flex 容器中的子元素都排在一条线(又称“轴线”)上。子元素尺寸总和大于 Flex 容器尺寸时,子元素尺寸会自动挤压。
wrap 属性控制当子元素主轴尺寸之和大于容器主轴尺寸时,Flex 是单行布局还是多行布局。在多行布局时,通过交叉轴方向,确认新行排列方向。
参数:wrap
值:枚举 FlexWrap
示例代码
@Entry
@Component
struct Index {
build() {
Flex({ wrap:FlexWrap.Wrap }) {
Text('1')
.width('33%')
.height(30)
.backgroundColor(Color.Orange)
Text('2')
.width('33%')
.height(30)
.backgroundColor(Color.Pink)
Text('3')
.width('33%')
.height(30)
.backgroundColor(Color.Orange)
Text('4')
.width('33%')
.height(30)
.backgroundColor(Color.Pink)
}
.width('100%')
.height(200)
.backgroundColor('#ccc')
}
}
1.6. 综合案例-菜单
1.6.1. 参考代码
@Entry
@Component
struct Index {
build() {
Column() {
Text('阶段选择')
.fontWeight(600)
.fontSize(24)
.width('100%')
.padding(15)
Flex({ wrap: FlexWrap.Wrap }) {
Text('ArkUI')
.padding(10)
.margin(5)
.backgroundColor('#f6f7f9')
Text('ArkTS')
.padding(10)
.margin(5)
.backgroundColor('#f6f7f9')
Text('界面开发')
.padding(10)
.margin(5)
.backgroundColor('#f6f7f9')
Text('系统能力')
.padding(10)
.margin(5)
.backgroundColor('#f6f7f9')
Text('权限控制')
.padding(10)
.margin(5)
.backgroundColor('#f6f7f9')
Text('元服务')
.padding(10)
.margin(5)
.backgroundColor('#f6f7f9')
}
}
.width('100%')
.height('100%')
.padding(10)
}
}
1.7. 自适应拉伸
1.7.1. flexGrow
作用:设置父容器的剩余空间分配给此属性所在组件的比例。用于分配父组件的剩余空间
属性:flexGrow(数字)
参数:数字,占用父级剩余尺寸的份数
示例代码
@Entry
@Component
struct Index {
build() {
Flex() {
Text('内容1')
.width(60)
.height(100)
.backgroundColor(Color.Pink)
Text('内容2')
.height(100)
.backgroundColor(Color.Orange)
// 占用父组件剩余空间1份
.flexGrow(1)
Text('内容3')
.height(100)
.backgroundColor(Color.Pink)
// 占用父组件剩余空间1份
.flexGrow(1)
}
.width('100%')
.height(100)
.backgroundColor('#ccc')
}
}
1.7.2. flexBasis
作用:设置子元素在父容器主轴方向上的基准尺寸。
属性:flexBasis(数字)
参数:数字,基准尺寸(单位vp)
@Entry
@Component
struct Index {
build() {
Flex() {
Text('内容1')
.width(60)
.height(100)
.backgroundColor(Color.Pink)
.flexBasis(60)
Text('内容2')
.height(100)
.backgroundColor(Color.Orange)
.flexGrow(1)
.flexBasis(120)
Text('内容3')
.height(100)
.backgroundColor(Color.Pink)
.flexGrow(1)
}
.width('100%')
.height(100)
.backgroundColor('#ccc')
}
}
-
如果设置了该值,则子项占用的空间为设置的值;如果没设置该属性,那子项的空间为 width/height 的值
-
flexGrow 基于 flexBasis 分配父组件剩余空间
2. 定位
作用:改变组件位置
分类:
● 绝对定位:position,相对父组件左上角进行偏移
● 相对定位:offset,相对自身左上角进行偏移
2.1. 绝对定位
属性:position()
参数:{x: 水平偏移量, y: 垂直偏移量}
偏移量取值
● 数字,单位是vp
● 百分比,参照父组件尺寸计算结果
示例代码
@Entry
@Component
struct Index {
build() {
Column() {
Text('文字内容')
.width(80)
.height(40)
.backgroundColor(Color.Pink)
.position({ x: 0, y: 0 })
}
.width('100%')
.height(200)
.backgroundColor('#ccc')
}
}
绝对定位特点:
-
参照父组件左上角进行偏移
-
绝对定位后的组件不再占用自身原有位置
2.2. 相对定位
属性:offset()
参数:{x: 水平偏移量, y: 垂直偏移量}
偏移量取值
●. 数字,单位是vp
●. 百分比,参照父组件尺寸计算结果
@Entry
@Component
struct Index {
build() {
Column() {
Text('内容1')
.width(80)
.height(40)
.backgroundColor(Color.Pink)
Text('内容2')
.width(80)
.height(40)
.backgroundColor(Color.Orange)
// 占位
.offset({ x: 100, y: -30 })
Text('内容3')
.width(80)
.height(40)
.backgroundColor(Color.Brown)
}
.width('100%')
.height(200)
.backgroundColor('#ccc')
}
}
相对定位特点:
-
相对自身左上角进行偏移
-
相对定位后的组件仍然占用自身原有位置
2.3. 案例-人气热播故事
2.3.1. 参考代码
@Entry
@Component
struct Index {
build() {
Column() {
Column() {
// 图片
Image($r('app.media.moco'))
.width('100%')
.aspectRatio(0.8)
.borderRadius(8)
// 文字
Row({ space: 10}) {
Image($r('app.media.ic_device_earphone_roc_filled'))
.width(20)
.backgroundColor('#0cbff9')
.padding(3)
.borderRadius(10)
.fillColor('#fff')
Text('飞狗MOCO')
.fontSize(16)
.fontColor('#4b3635')
.fontWeight(600)
}
.width('100%')
.padding(5)
.alignItems(VerticalAlign.Top)
// VIP Text('VIP')
.width(34)
.height(18)
.backgroundColor('#f3912e')
.border({ width: 2, color: '#ffe7a0' })
.borderRadius({ topLeft: 8, bottomRight: 8 })
.position({x: 0, y:0})
.fontSize(12)
.fontColor('#ffe788')
.textAlign(TextAlign.Center)
.fontWeight(700)
.fontStyle(FontStyle.Italic)
}
.width('45%')
}
.padding(10)
}
}
2.4. Z 序控制
定位后的组件,默认后定义的组件在最上面显示,可以通过 zIndex 属性调整显示层级
属性:zIndex(数字)
特点:取值为整数数字,取值越大,显示层级越高
@Entry
@Component
struct Index {
build() {
Column() {
Text('内容1')
.width(100)
.height(50)
.backgroundColor(Color.Pink)
.position({x: 0, y:0})
// Z 轴显示顺序,取值越大,显示层级越高
.zIndex(1)
Text('内容2')
.width(200)
.height(60)
.backgroundColor(Color.Orange)
.position({x: 50,y: 30})
}
.width(300)
.height(200)
.backgroundColor('#ccc')
}
}
3. 层叠布局
层叠布局(StackLayout)用于在屏幕上预留一块区域来显示组件中的元素,提供元素可以重叠的布局。层叠布局通过 Stack 容器组件实现位置的固定定位与层叠,容器中的子元素依次入栈,后一个子元素覆盖前一个子元素,子元素可以叠加,也可以设置位置。
层叠布局具有较强的页面层叠、位置定位能力,其使用场景有广告、卡片层叠效果等。
3.1. 基本使用
Stack 组件为容器组件,容器内可包含各种子元素。其中子元素默认进行居中堆叠。子元素被约束在Stack下,进行自己的样式定义以及排列。
示例代码
@Entry
@Component
struct Index {
build() {
Column(){
Stack() {
Column(){
}
.width('90%')
.height(130)
.backgroundColor(Color.Gray)
Text('text')
.width('60%')
.height('60%')
.backgroundColor(Color.Orange)
Button('button')
.width('30%')
.height('30%')
.backgroundColor('#ff8ff3eb')
.fontColor('#000') }
.width('100%')
.height(150)
.backgroundColor(Color.Pink)
}
.margin(10)
}
}
3.2. 对齐方式
参数:alignContent
取值:枚举 Alignment
示例代码
@Entry
@Component
struct Index {
build() {
Column(){
Stack({ alignContent: Alignment.BottomEnd }) {
Column(){}
.width('90%')
.height(130)
.backgroundColor(Color.Gray)
Text('text')
.width('60%')
.height('60%')
.backgroundColor(Color.Orange)
Button('button')
.width('30%')
.height('30%')
.backgroundColor('#ff8ff3eb')
.fontColor('#000')
}
.width('100%')
.height(150)
.backgroundColor(Color.Pink)
}
.margin(10)
}
}
3.3. Z 序控制
属性:zIndex(数字)
特点:取值为整数数字,取值越大,显示层级越高
示例代码
@Entry
@Component
struct Index {
build() {
Column(){
Stack({ alignContent: Alignment.BottomEnd }) {
Column(){}
.width('90%')
.height(130)
.backgroundColor(Color.Gray)
Text('text')
.width('60%')
.height('60%')
.backgroundColor('rgba(0,0,0,0.3)')
// Z 序:显示在按钮上一层
.zIndex(1) Button('button')
.width('30%')
.height('30%')
.backgroundColor('#ff8ff3eb')
.fontColor('#000')
}
.width('100%')
.height(150)
.backgroundColor(Color.Pink)
}
.margin(10)
}
}
4. 综合案例-B站-视频卡片
4.1. 布局思路
区域划分:
●. 图片区域(层叠布局)
○. 图片组件
○. 文字内容:播放 + 评论 + 时长(Flex 布局)
●. 文字区域
○. 标题文字
4.2. 参考代码
@Entry
@Component
struct Index {
build() {
Column(){
Column() {
// 图片区域 -- 层叠布局
Stack({ alignContent: Alignment.BottomStart}) {
// 图片组件
Image($r('app.media.tieyi'))
.width(200)
.height(125)
.objectFit(ImageFit.Cover)
.borderRadius({
topLeft: 10,
topRight: 10
})
// 文字内容
Row() {
// 播放量
Row({ space: 5}) {
Image($r('app.media.ic_bofangshu'))
.width(16)
.fillColor('#fff')
Text('282万')
.fontColor('#fff')
.fontSize(12)
}
.margin({right: 5})
// 评论数
Row({ space: 5}) {
Image($r('app.media.ic_ziyuan'))
.fillColor('#fff')
.width(14)
Text('8655')
.fontColor('#fff')
.fontSize(12)
}
// 空白填充组件
Blank()
// 右侧时长
Text('4:33')
.fontColor('#fff')
.fontSize(12)
}
.width('100%')
.height(24)
.padding({left: 5, right: 5})
}
// 文字区域
Column() {
// 标题文字
Text('【凤凰传奇新歌】欢迎来到国风统治区:唢呐一响神曲《铁衣流派推广曲》')
.fontSize(13)
.textOverflow({overflow: TextOverflow.Ellipsis})
.maxLines(2
.lineHeight(16)
// 点赞更多
Row(){
Text('19万点赞')
.padding(3)
.backgroundColor('#fef0ef')
.fontSize(10)
.fontColor('#e66c43')
Image($r('app.media.ic_gengduo'))
.width(14)
.fillColor('#bfbfbf')
}
.width('100%')
.margin({top: 10})
.justifyContent(FlexAlign.SpaceBetween)
}
.padding(5)
}
.width(200)
.height(200)
.backgroundColor('#fff')
.borderRadius(10)
}
.width('100%')
.height('100%')
.backgroundColor('#f5f6f7')
.padding(10)
}
}
```3