最近闲下来,开始学习有关鸿蒙的知识,以下是本人在学习中对鸿蒙存在的各种布局进行学习探究。
1.线性布局
1.1 Row组件
struct Demo1 {
@State message: string = 'Hello World'
build() {
Row() {
Row() {
Column().width(100).height(200).backgroundColor(Color.Red)
Column().width(100).height(200).backgroundColor(Color.Blue)
Column().width(100).height(200).backgroundColor(Color.Pink)
}.width('100%').justifyContent(FlexAlign.SpaceEvenly)
}
.height('100%')
}
}
如果row组件套row组件会默认居中,需要加上.alignItems(VerticalAlign.Top)
@Entry
@Component
struct Demo1 {
@State message: string = 'Hello World'
build() {
Row() {
Row() {
Column().width(100).height(200).backgroundColor(Color.Red)
Column().width(100).height(200).backgroundColor(Color.Blue)
Column().width(100).height(200).backgroundColor(Color.Pink)
}.width('100%').justifyContent(FlexAlign.SpaceEvenly)
}
.height('100%').alignItems(VerticalAlign.Top)
}
}
1.2 Column组件
@Entry
@Component
struct Demo1 {
@State message: string = 'Hello World'
build() {
Column() {
Row() {
Column().width(100).height(200).backgroundColor(Color.Red)
Column().width(100).height(200).backgroundColor(Color.Blue)
Column().width(100).height(200).backgroundColor(Color.Pink)
}.width('100%').justifyContent(FlexAlign.SpaceEvenly).height(200)
Column(){
Column().width(200).height(100).backgroundColor(Color.Red)
Column().width(200).height(100).backgroundColor(Color.Blue)
Column().width(200).height(100).backgroundColor(Color.Yellow)
}.height(100)
}
.height('100%').padding({
top:20
})
}
}
注意 :在使用Row中写组件会导致内部的组件相互遮挡,如下图:上面的是Row嵌套下面的用Column嵌套
2.弹性布局
2.1Flex定义
在 Flex 布局 中,有两个重要的概念:主轴和交叉轴。
- 主轴:就像一条基准线,决定了子元素排列的方向。子元素默认会沿着这条主轴一个接一个排开。主轴的起点是开始的位置,终点是结束的位置。
- 交叉轴:和主轴垂直,是另一条基准线。交叉轴的起点和终点,分别是它的开始和结束位置。
简单来说,主轴是控制子元素横着排还是竖着排的轴线,而交叉轴就是和主轴垂直的那条轴线
与线性布局相比,它支持换行,但是没有滚动条
2.2Flex使用
@Entry
@Component
struct Page {
@State message: string = 'Hello World';
build() {
Flex({
direction: FlexDirection.Row,
wrap:FlexWrap.Wrap
}) {
Row()
.width(100)
.height(50)
.backgroundColor(Color.Red).margin({
bottom:10,
right:10,
left:10
})
Row()
.width(100)
.height(50)
.backgroundColor(Color.Red).margin({
bottom:10,
right:10,
left:10
})
Row()
.width(100)
.height(50)
.backgroundColor(Color.Red).margin({
bottom:10,
right:10,
left:10
})
Row()
.width(100)
.height(50)
.backgroundColor(Color.Red).margin({
bottom:10,
right:10,
left:10
})
Row()
.width(100)
.height(50)
.backgroundColor(Color.Red).margin({
bottom:10,
right:10,
left:10
})
Row()
.width(100)
.height(50)
.backgroundColor(Color.Red).margin({
bottom:10,
right:10,
left:10
})
}.backgroundColor(Color.Yellow).width("100%").height('100%')
}
}
3.相对布局
RelativeContainer为采用相对布局的容器,支持容器内部的子元素设置相对位置关系,适用于界面复杂场景的情况,对多个子组件进行对齐和排列。它具备以下特点
- 锚点布局
- 元素可以通过相对于父容器或其他兄弟元素的锚点来指定位置。
- 使用锚点属性(如
startToStartOf
、endToEndOf
)进行位置定义。 - 父容器的默认 ID 是
"__Container__"
,你可以用它作为锚点的参考。
- 唯一 ID
- 每个子元素需要一个唯一的 ID,用于引用和定位。没有 ID 的元素无法参与相对定位。
- 灵活性
- 支持复杂的相对位置设置,例如对齐到左、右、上、下、中心等。
- 提供了自由设计布局的能力,适用于动态或复杂的 UI 场景。
3.1 RelativeContainer定义
@Entry
@Component
struct RelativeContainerCase {
build() {
Column() {
RelativeContainer() {
Text("card1")
.fontSize(25)
.width(160)
.height(150)
.textAlign(TextAlign.End)
.backgroundColor(Color.Green)
Text("card2")
.fontSize(25)
.width(90)
.height(130)
.backgroundColor(Color.Yellow)
Text("card3")
.fontSize(25)
.backgroundColor(Color.Red)
} .width("100%")
.height(190)
.backgroundColor(Color.Blue)
} .size({width: "100%", height: "100%"})
.backgroundColor(Color.Orange)
.padding(10)
}
}
3.2 RelativeContainer对齐规则
RelativeContainer对子组件的对齐方式分为水平方向和竖直方向:
- 垂直方向对齐:可选择
VerticalAlign.Top
(顶部对齐)、VerticalAlign.Center
(垂直居中)和VerticalAlign.Bottom
(底部对齐)。 - 水平方向对齐:可选择
HorizontalAlign.Start
(左对齐)、HorizontalAlign.Center
(水平居中)和HorizontalAlign.End
(右对齐)。
3.2.1垂直方向对齐
@Entry
@Component
struct RelativeContainerRuleCase {
build() {
Row(){
Column(){
RelativeContainer() {
//当前元素的竖直方向的上边对应描点容器的上边
Text("Top-Top").backgroundColor(Color.Red).width(150).height(50).fontColor("#ffffff").alignRules({
top:{anchor:"__container__",align:VerticalAlign.Top}
})
//当前元素的竖直方向的上边对应描点容器的中间
Text("Top-Center").backgroundColor(Color.Red).width(150).height(50).fontColor("#ffffff").alignRules({
top:{anchor:"__container__",align:VerticalAlign.Center}
})
//当前元素的竖直方向的上边对应描点容器的下边
Text("Top-Bottom").backgroundColor(Color.Red).width(150).height(50).fontColor("#ffffff").alignRules({
top:{anchor:"__container__",align:VerticalAlign.Bottom}
})
//当前元素的竖直方向的中间对应描点容器的上边
Text("Center-Top").backgroundColor(Color.Orange).width(150).height(50).fontColor("#ffffff").alignRules({
center:{anchor:"__container__",align:VerticalAlign.Top}
})
//当前元素的竖直方向的中间对应描点容器的中间
Text("Center-Center").backgroundColor(Color.Orange).width(150).height(50).fontColor("#ffffff").alignRules({
center:{anchor:"__container__",align:VerticalAlign.Center}
})
//当前元素的竖直方向的中间对应描点容器的下边
Text("Center-Bottom").backgroundColor(Color.Orange).width(150).height(50).fontColor("#ffffff").alignRules({
center:{anchor:"__container__",align:VerticalAlign.Bottom}
})
//当前元素的竖直方向的下边对应描点容器的上边
Text("Bottom-Top").backgroundColor(Color.Blue).width(150).height(50).fontColor("#ffffff").alignRules({
bottom:{anchor:"__container__",align:VerticalAlign.Top}
})
//当前元素的竖直方向的下边对应描点容器的中间
Text("Bottom-Center").backgroundColor(Color.Blue).width(150).height(50).fontColor("#ffffff").alignRules({
bottom:{anchor:"__container__",align:VerticalAlign.Center}
})
//当前元素的竖直方向的下边对应描点容器的下边
Text("Bottom-Bottom").backgroundColor(Color.Blue).width(150).height(50).fontColor("#ffffff").alignRules({
bottom:{anchor:"__container__",align:VerticalAlign.Bottom}
})
}
.height(300)
.width('100%').backgroundColor(Color.Pink)
}.width("100%")
}.height("100%")
}
}
3.2.2 水平方向对齐
@Entry
@Component
struct RelativeContainerRuleCase2 {
@State message: string = 'Hello World';
build() {
Row() {
Column() {
RelativeContainer() {
//当前元素的左边与锚点元素的左边起始位置对齐
Text("Left-Start").width(100).height(50).fontColor("#fff").backgroundColor(Color.Green).alignRules({
left:{anchor:"__container__",align:HorizontalAlign.Start}
})
//当前元素的左边与锚点元素的中间位置对齐
Text("Left-Center").width(100).height(50).fontColor("#fff").backgroundColor(Color.Green).alignRules({
left:{anchor:"__container__",align:HorizontalAlign.Center}
})
//当前元素的左边与锚点元素的右边结束位置对齐
Text("Left-End").width(100).height(50).fontColor("#fff").backgroundColor(Color.Green).alignRules({
left:{anchor:"__container__",align:HorizontalAlign.End},
})
//当前元素的中间位置与锚点元素的左边起始位置对齐
Text("Middle-Start").width(100).height(50).fontColor("#fff").backgroundColor(Color.Blue).alignRules({
middle:{anchor:"__container__",align:HorizontalAlign.Start},
center:{anchor:"__container__",align:VerticalAlign.Center}
})
//当前元素的中间位置与锚点元素的中间位置对齐
Text("Middle-Center").width(100).height(50).fontColor("#fff").backgroundColor(Color.Blue).alignRules({
middle:{anchor:"__container__",align:HorizontalAlign.Center},
center:{anchor:"__container__",align:VerticalAlign.Center}
})
//当前元素的中间位置与锚点元素的右边结束位置对齐
Text("Middle-End").width(100).height(50).fontColor("#fff").backgroundColor(Color.Blue).alignRules({
middle:{anchor:"__container__",align:HorizontalAlign.End},
center:{anchor:"__container__",align:VerticalAlign.Center}
})
//当前元素的右边与锚点元素的左边起始位置对齐
Text("Right-Start").width(100).height(50).textAlign(TextAlign.End).fontColor("#fff").backgroundColor(Color.Red).alignRules({
right:{anchor:"__container__",align:HorizontalAlign.Start},
bottom:{anchor:"__container__",align:VerticalAlign.Bottom},
})
//当前元素的右边与锚点元素的中间位置对齐
Text("Right-Center").width(100).height(50).textAlign(TextAlign.End).fontColor("#fff").backgroundColor(Color.Red).alignRules({
right:{anchor:"__container__",align:HorizontalAlign.Center},
bottom:{anchor:"__container__",align:VerticalAlign.Bottom},
})
//当前元素的右边与锚点元素的右边结束位置对齐
Text("Right-End").width(100).height(50).textAlign(TextAlign.End).fontColor("#fff").backgroundColor(Color.Red).alignRules({
right:{anchor:"__container__",align:HorizontalAlign.End},
bottom:{anchor:"__container__",align:VerticalAlign.Bottom},
})
}.width("60%").height(400).backgroundColor(Color.Pink)
}.width("100%")
}.height("100%")
}
}
4.堆叠布局
4.1子组件层级控制
Stack容器中⼦组件的层级除了可按照添加顺序决定,还能通过 Index 的值越⼤,层级越⾼
4.2 案例
import { promptAction } from '@kit.ArkUI';
@Entry
@Component
struct StackCase {
@State content: string = '';
searchContent() {
promptAction.showToast({
message: this.content
})
}
enabledChange() {
return this.content !== ""
}
build() {
Column(){
Image($r("app.media.baidu")).height(200).width("100%")
Row() {
Stack() {
TextInput({ placeholder: "请输入需要搜索的内容", text: $$this.content })
.width("100%")
.height(40)
.position({ x: 0, y: 0 })
.zIndex(1)
.borderRadius({
topLeft: 10,
topRight: 0,
bottomLeft: 10,
bottomRight: 0
}).padding({
right:60
})
Image($r("app.media.microphone")).height(20).width(20).position({ x: 200, y: 10 }).zIndex(2)
Image($r("app.media.camera")).height(20).width(20).position({ x: 230, y: 10 }).zIndex(2)
}.width(260).height("100%")
Button("百度一下")
.borderRadius({
topLeft: 0,
topRight: 10,
bottomLeft: 0,
bottomRight: 10
})
.layoutWeight(1)
.height("100%").type(ButtonType.Normal)
.onClick(() => {
this.searchContent()
})
.enabled(this.enabledChange())
}.width("100%").height(40)
}.alignItems(HorizontalAlign.Center).width("100%").padding(10)
}
}
5.grid布局
5.1grid布局的使用
- Grid可以设置columnsTemplate和rowsTemplate
- columnsTemplate是设置横向的分配,如果设置1fr 1fr表示,等分为两份,如果设置1fr 2fr表示左边一份,右边一份
- 在设置columnsTemplate不设置rowsTemplate的情况下,如果内容超出容器区域,会自动出现滚动条
- columnsGap设置列和列之间的间距,rowsGap设置行和行之间的间距
- Grid布局具有滚动条
5.2案例
@Entry
@Component
struct GridCase {
@State message: string = 'Hello World';
@State services: Array<string> = []
build() {
Grid() {
GridCaseItem()
GridCaseItem()
GridCaseItem()
GridCaseItem()
GridCaseItem()
GridCaseItem()
GridCaseItem()
GridCaseItem()
GridCaseItem()
GridCaseItem()
GridCaseItem()
GridCaseItem()
GridCaseItem()
GridCaseItem()
GridCaseItem()
GridCaseItem()
}
.width('100%')
.height("100%")
.columnsTemplate("1fr 1fr")
.columnsGap(10)
.rowsGap(10).padding(10)
}
}
@Component
struct GridCaseItem {
build() {
GridItem() {
Row() {
Text("内容").width('100%').textAlign(TextAlign.Center)
}.height(200).borderRadius(4).backgroundColor(Color.Pink)
}
}
}