【HarmonyOS4+Next】Column和Row组件详解
⭐本期内容:【HarmonyOS4+Next】Column和Row组件详解
🏆系列专栏:鸿蒙HarmonyOS4+NEXT:探索未来智能生态新纪元
文章目录
- 前言
- 基本概念
- Column组件
- Row组件
- 主要属性
- Column和Row的接口定义
- 对齐方式
- justifyContent属性
- alignItems属性
- Column容器的alignItems属性
- Row容器的alignItems属性
- 间距设置
- 自适应拉伸
- 使用百分比宽高
- 使用layoutWeight属性
- 使用Blank组件
- 实际应用示例
- 登录界面
- 列表项
- 性能优化
- 总结
前言
在HarmonyOS的ArkUI框架中,布局是构建应用界面的基础。其中Column
和Row
是两个最常用的线性布局容器组件,它们帮助开发者以简单灵活的方式组织和排列界面元素。
基本概念
在了解Column和Row之前,我们需要先理解ArkUI布局中的两个重要概念:主轴和交叉轴
-
主轴:指布局容器的主要排列方向
- Column的主轴是垂直方向(从上到下)
- Row的主轴是水平方向(从左到右)
-
交叉轴:与主轴垂直的轴
- Column的交叉轴是水平方向
- Row的交叉轴是垂直方向
Column组件
Column
是一个沿垂直方向布局的容器组件,它将子组件从上到下依次排列。
Column() {
Text('第一项')
Text('第二项')
Text('第三项')
Text('第四项')
Text('第五项')
}
Row组件
Row
是一个沿水平方向布局的容器组件,它将子组件从左到右依次排列。
Row() {
Text('第一项')
Text('第二项')
Text('第三项')
Text('第四项')
Text('第五项')
}
主要属性
Column和Row的接口定义
// Column接口定义
interface ColumnInterface {
(value?: { space?: string | number }): ColumnAttribute;
}
// Row接口定义
interface RowInterface {
(value?: { space?: string | number }): RowAttribute;
}
两者都有一个可选参数space
,表示子组件在主轴方向上的间距。
对齐方式
Column和Row提供了两种对齐方式的属性:
- justifyContent:控制子组件在主轴方向上的对齐方式
- alignItems:控制子组件在交叉轴方向上的对齐方式
justifyContent属性
justifyContent
接受一个FlexAlign
类型的参数,用于设置子组件在主轴方向上的排列方式。FlexAlign
定义了以下几种类型:
- FlexAlign.Start:元素在主轴方向首端对齐,第一个元素与容器起始端对齐,后续元素依次排列
- FlexAlign.Center:元素在主轴方向中心对齐,所有元素居中,首尾距离相等
- FlexAlign.End:元素在主轴方向尾部对齐,最后一个元素与容器末端对齐,其他元素依次向前排列
- FlexAlign.SpaceBetween:元素在主轴方向均匀分布,首尾元素分别与容器两端对齐,中间元素间距相等
- FlexAlign.SpaceAround:元素在主轴方向均匀分布,首尾元素与容器边缘的距离是元素间距的一半
- FlexAlign.SpaceEvenly:元素在主轴方向等间距分布,包括首尾元素与容器边缘的距离也相等
Column() {
Text('文本1').width('80%').height(50).backgroundColor('#FF3333')
Text('文本2').width('60%').height(50).backgroundColor('#33FF33')
Text('文本3').width('40%').height(50).backgroundColor('#3333FF')
}
.width('100%')
.height(300)
.backgroundColor('#EEEEEE')
.justifyContent(FlexAlign.SpaceBetween)
alignItems属性
Column容器的alignItems属性
Column
容器的alignItems
接受一个HorizontalAlign
类型的参数,用于设置子组件在水平方向(交叉轴)上的对齐方式:
- HorizontalAlign.Start:子组件在水平方向上按照起始端对齐
- HorizontalAlign.Center(默认值):子组件在水平方向上居中对齐
- HorizontalAlign.End:子组件在水平方向上按照末端对齐
Column() {
Text('文本1').width('60%').height(50).backgroundColor('#FF3333')
Text('文本2').width('80%').height(50).backgroundColor('#33FF33')
Text('文本3').width('40%').height(50).backgroundColor('#3333FF')
}
.width('100%')
.height(300)
.backgroundColor('#EEEEEE')
.alignItems(HorizontalAlign.Start)
Row容器的alignItems属性
Row
容器的alignItems
接受一个VerticalAlign
类型的参数,用于设置子组件在垂直方向(交叉轴)上的对齐方式:
- VerticalAlign.Top:子组件在垂直方向上居顶部对齐
- VerticalAlign.Center(默认值):子组件在垂直方向上居中对齐
- VerticalAlign.Bottom:子组件在垂直方向上居底部对齐
Row() {
Text('文本1').width(80).height('40%').backgroundColor('#FF3333')
Text('文本2').width(80).height('60%').backgroundColor('#33FF33')
Text('文本3').width(80).height('80%').backgroundColor('#3333FF')
}
.width('100%')
.height(300)
.backgroundColor('#EEEEEE')
.alignItems(VerticalAlign.Bottom)
间距设置
通过space
属性,可以设置子组件在排列方向上的间距,使各子组件等间距排列。
Column({ space: 20 }) {
Text('文本1').width('90%').height(80).backgroundColor('#FF3333')
Text('文本2').width('90%').height(80).backgroundColor('#33FF33')
Text('文本3').width('90%').height(80).backgroundColor('#3333FF')
}
.width('100%')
.backgroundColor('#EEEEEE')
⚠️ 注意:如果设置了space
属性,justifyContent
属性将不再生效。
自适应拉伸
在实际开发中,我们常常需要让组件根据屏幕大小自适应调整。
使用百分比宽高
@Entry
@Component
struct WidthExample {
build() {
Column() {
Row() {
Column() {
Text('左侧 width 20%')
.textAlign(TextAlign.Center)
}.width('20%').backgroundColor('#ffb3def5').height('100%')
Column() {
Text('中间 width 50%')
.textAlign(TextAlign.Center)
}.width('50%').backgroundColor('#ff3397be').height('100%')
Column() {
Text('右侧 width 30%')
.textAlign(TextAlign.Center)
}.width('30%').backgroundColor('#ff4880e2').height('100%')
}.backgroundColor('#ff090660').height('30%')
}
}
}
使用layoutWeight属性
layoutWeight
属性允许子组件按照指定的权重比例分配剩余空间:
@Entry
@Component
struct LayoutWeightExample {
build() {
Column() {
Text('比例为 1:2:3').width('100%')
Row() {
Column() {
Text('layoutWeight(1)')
.textAlign(TextAlign.Center)
}.layoutWeight(1).backgroundColor('#ff679bd9').height('100%')
Column() {
Text('layoutWeight(2)')
.textAlign(TextAlign.Center)
}.layoutWeight(2).backgroundColor('#ff2e84ea').height('100%')
Column() {
Text('layoutWeight(3)')
.textAlign(TextAlign.Center)
}.layoutWeight(3).backgroundColor('#ff155b92').height('100%')
}.backgroundColor('#FFD306').height('30%')
}
}
}
使用Blank组件
Blank
组件可以在线性布局中填充剩余空间。
@Entry
@Component
struct BlankExample {
build() {
Row() {
Text('左侧').fontSize(20)
Blank() // 填充中间所有剩余空间
Text('右侧').fontSize(20)
}
.width('100%')
.padding(10)
.backgroundColor('#ff386da2')
}
}
实际应用示例
登录界面
@Entry
@Component
struct LoginPage {
@State username: string = ''
@State password: string = ''
@State rememberMe: boolean = false
build() {
Column({ space: 20 }) {
Image('logo.png')
.width(80)
.height(80)
.margin({ top: 60, bottom: 20 })
TextInput({ placeholder: '用户名' })
.width('80%')
.height(50)
.onChange((value: string) => {
this.username = value
})
TextInput({ placeholder: '密码' })
.width('80%')
.height(50)
.type(InputType.Password)
.showPasswordIcon(true)
.onChange((value: string) => {
this.password = value
})
Button('登录')
.width('80%')
.height(50)
.backgroundColor('#0099FF')
.fontColor(Color.White)
.borderRadius(8)
.onClick(() => {
// 处理登录逻辑
console.info(`登录: 用户名=${this.username}, 密码=${this.password}`)
})
Row() {
Checkbox()
.select(this.rememberMe)
.onChange((value: boolean) => {
this.rememberMe = value
})
Text('记住我')
.fontSize(14)
.fontColor('#36D')
.margin({ left: 5 })
}
.width('80%')
.justifyContent(FlexAlign.Start)
}
.width('100%')
.height('100%')
.backgroundColor('#F1F3F5')
.justifyContent(FlexAlign.Start)
.alignItems(HorizontalAlign.Center)
}
}
列表项
@Entry
@Component
struct ListItemExample {
build() {
Column() {
// 列表标题
Text('我的设备列表')
.fontSize(22)
.fontWeight(FontWeight.Bold)
.width('100%')
.padding(16)
// 列表项1
Row() {
Image('device1.png')
.width(50)
.height(50)
.borderRadius(25)
Column() {
Text('智能手表')
.fontSize(18)
.fontWeight(FontWeight.Medium)
Text('已连接')
.fontSize(14)
.fontColor('#66A')
}
.layoutWeight(1)
.alignItems(HorizontalAlign.Start)
.margin({ left: 12 })
Text('设置')
.fontColor('#0099FF')
}
.width('90%')
.padding(16)
.backgroundColor(Color.White)
.borderRadius(8)
.margin({ top: 8 })
// 列表项2
Row() {
Image('device2.png')
.width(50)
.height(50)
.borderRadius(25)
Column() {
Text('智能音箱')
.fontSize(18)
.fontWeight(FontWeight.Medium)
Text('离线')
.fontSize(14)
.fontColor('#888')
}
.layoutWeight(1)
.alignItems(HorizontalAlign.Start)
.margin({ left: 12 })
Text('设置')
.fontColor('#0099FF')
}
.width('90%')
.padding(16)
.backgroundColor(Color.White)
.borderRadius(8)
.margin({ top: 8 })
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
.alignItems(HorizontalAlign.Center)
}
}
性能优化
在开发过程中,合理使用Column和Row可以优化应用性能:
- 避免嵌套过深:减少布局层级可以提高渲染效率
- 使用懒加载:对于大列表,使用
LazyForEach
加载数据 - 合理设置尺寸:显式设置组件尺寸可以减少重新计算布局的次数
- 替代Flex:在一些场景下,使用Column和Row替代Flex可以获得更好的性能
总结
今日学习之旅已圆满收笔,愿每位君子都满载而归,心有所悟!🤩
若你对这探索之旅情有独钟,何不紧随此专栏的步伐?新知如潮,连绵不绝,将与你共绘思维的绚烂篇章,舞动智慧的火花!😎
轻轻一点下方名片,加入我们的粉丝大家庭,让我们在知识的浩瀚海洋中再次相逢,携手见证智慧之花的绚丽绽放,共享求知的喜悦与盛宴!👍