大家好我是牛牛,一名软件开发从业者,无意中接触到了鸿蒙移动端开发,对鸿蒙操作系统产生了极大的兴趣,作者将从无到有开发出一款鸿蒙原生APP。每天写一篇关于鸿蒙开发的技术文章。欢迎大家踊跃订阅➕关注,文章中有什么 不妥之处可以在评论区中指出。
注意:最好是有开发经验的伙伴来阅读系列文章。零基础的同学可以先去了解一下TypeScript从最基本的开发语言进行学起
前言
上篇文章中《一百天挑战学会HarmanyOS——HarmanyOS 的开发模型与组件结构》 介绍了鸿蒙的开发模型与ArkUI中组件的基本结构,让大家认识了 ArkUI 初始化项目时所使用的一些组件,那么这一章节将为大家介绍 HarmanyOS 开发中布局方式。
系统组件(ArkUI)
ArkUI 将组件分为这么几类(随着 NEXT 版本的不断迭代更新,可能还会新增许多组件)
- 基础组件
- 容器组件
- 媒体组件
- 绘制组件
- 高级组件
- 安全组件
- Ability Kit (在UIAbility组件可以使用ArkUI提供的组件、事件、动效、状态管理等能力。)
基本组件的使用
文章中只提供常用的部分组件的属性实现,只为展示组件的示例,更详细的配置可以查看官方的 API 文档UI 文档
Text 文本组件
示例代码:
@Entry
@Component
struct FlexCase {
build() {
Column(){
// 文本组件
Text('你好鸿蒙')
// 文本大小
.fontSize('50')
// 文本颜色
.fontColor(Color.Red)
// 字体宽度
.fontWeight(700)
}
.height('100%')
.width('100%')
.justifyContent(FlexAlign.Center)
}
}
编译结果:
Column 列组件,纵向排列,布局主轴是Y轴 容器中可以放任意子组件
示例代码:
@Entry
@Component
struct FlexCase {
build() {
// Column 列组件,纵向排列 主轴是 Y 轴
// space 设置column容器中每个元素的间距
Column({space:20}){
Row()
.width(200)
.height(100)
.backgroundColor(Color.Red)
Row()
.width(200)
.height(100)
.backgroundColor(Color.Blue)
Row()
.width(200)
.height(100)
.backgroundColor(Color.Pink)
}
// 高度
.height('100%')
// 宽度
.width('100%')
// 主轴居中对齐
.justifyContent(FlexAlign.Center)
}
}
编译结果:
Row 行组件,横向排列,布局主轴是X 容器中可以放任意子组件
Row组件默认情况下,子组件内容会垂直方向居中- 内容超出不会换行
示例代码:
@Entry
@Component
struct FlexCase {
build() {
// Row 列组件,横向排列 主轴是 X 轴,超出屏幕永远不会换行
// space 设置Row容器中每个元素的间距
Row({space:20}){
Row()
.width(100)
.height(200)
.backgroundColor(Color.Red)
Row()
.width(100)
.height(200)
.backgroundColor(Color.Blue)
Row()
.width(100)
.height(200)
.backgroundColor(Color.Pink)
}
// 高度
.height('100%')
// 宽度
.width('100%')
// 主轴居中对齐
.justifyContent(FlexAlign.Center)
}
}
编译结果:
Flex 组件以弹性方式布局子组件的容器组件。(存在二次布局,官方推荐有性能要求,使用Column和Row代替)
示例代码:
@Entry
@Component
struct FlexCase {
build() {
Flex({
// 主轴横向排列
direction: FlexDirection.Row,
// 中间空隙平均分
justifyContent: FlexAlign.SpaceEvenly,
// 超出屏幕宽度换行
wrap: FlexWrap.Wrap,
// 内容居中显示
alignContent: FlexAlign.Center
}){
Row()
.width(100)
.height(200)
.backgroundColor(Color.Pink)
Row()
.width(100)
.height(200)
.backgroundColor(Color.Blue)
Row()
.width(100)
.height(200)
.backgroundColor(Color.Green)
Row()
.width(100)
.height(200)
.backgroundColor(Color.Orange)
Row()
.width(100)
.height(200)
.backgroundColor(Color.Brown)
}
.backgroundColor(Color.Grey)
.height('100%')
}
}
编译结果:
Button 按钮组件
示例代码:
@Entry
@Component
struct FlexCase {
build() {
Row(){
// 按钮组件
Button('这是一个按钮')
// 按钮类型
.type(ButtonType.Normal)
// 字体宽度
.fontWeight(700)
// 宽度
.width(200)
// 背景颜色
.backgroundColor("#07c160")
// 按钮的点击事件
.onClick(()=>{
})
}
.height('100%')
.width('100%')
.justifyContent(FlexAlign.Center)
}
}
编译结果:
TextInput 输入框组件
示例代码:
@Entry
@Component
struct FlexCase {
build() {
Column({space:20}){
// 输入框组件
TextInput({
// 提示文字
placeholder: '请输入文字'
})
TextInput({
placeholder: '请输入密码'
// 输入框类型
}).type(InputType.Password)
TextInput({
placeholder: '请输入验证码'
// 输入最大长度
}).maxLength(6)
}
.padding(20)
.height('100%')
.width('100%')
.justifyContent(FlexAlign.Center)
}
}
编译结果:
Image 组件
Image组件的参数也可以使用 $r() 进行本地资源的获取也可以是网络图片。 在使用模拟器运行时,需要配置网络权限
示例代码:
@Entry
@Component
struct FlexCase {
build() {
Column({space:20}){
Image("https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png")
.width(160)
.height(80)
}
.padding(20)
.height('100%')
.width('100%')
.justifyContent(FlexAlign.Center)
}
}
编译结果:
百度小案例
使用以上的组件可以实现一个百度搜索的小案例。大家也可以动手实操起来。
示例代码:
@Entry
@Component
struct FlexCase {
build() {
Column({ space: 20 }) {
// 百度图片
Image("https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png")
.width(160)
.height(80)
// 行布局
Row() {
// 输入框
TextInput()
// 圆角属性
.borderRadius({
topLeft: 6,
bottomLeft: 6
})
.height(40)
.layoutWeight(1)
// 背景颜色
.backgroundColor(Color.White)
// 边框颜色
.border({
color: "#c4c7ce",
width: 2
})
// 按钮
Button("百度一下")
.type(ButtonType.Normal)
.backgroundColor("#516aee")
.padding({
left: 10,
right: 10,
top: 6,
bottom: 6
})
// 位移
.translate({
x: -2
})
// 按钮圆角
.borderRadius({
topRight: 6,
bottomRight: 6
})
}
.padding({
left: 10,
right: 10
})
.width('100%')
}
.justifyContent(FlexAlign.Center)
.width('100%')
.height('100%')
}
}
编译结果:
Tips:
Row和Column的布局方式成为线性布局-不是横向排列就是纵向排列
- 线性布局中永远不会产生换行
- Flex布局-使用Flex组件-容器- 支持横向和纵向-弹性布局-支持换行
- 均不支持出现滚动条
Grid(网格容器,由“行”和“列”分割的单元格所组成,通过指定“项目”所在的单元格做出各种各样的布局。仅支持GridItem组件)
Grid布局
- 想要控制屏幕的分栏分几列,怎么分特别像前端的栅格布局
- Row组件默认情况下,里面的元素的纵向是居中的
- Column组件默认横向是居中的
- Grid组件下只能放置GridItem组件
Grid可以设置columnsTemplate和rowsTemplate ,columnsTemplate是设置横向的分配,如果设置 1fr 1fr 表示,等分为两份, 如果设置1fr 2fr表示左边一份,右边两份, 在设置columnsTemplate不设置rowsTemplate的情况下,如果内容超出容器区域,会自动出现滚动条 columnsGap设置列和列之间的间距,rowsGap设置行和行之间的间距
示例代码:
@Entry
@Component
struct FlexCase {
build() {
// 网格布局
Grid() {
// 自定义组件
GridItemCase()
GridItemCase()
GridItemCase()
GridItemCase()
GridItemCase()
GridItemCase()
GridItemCase()
GridItemCase()
GridItemCase()
GridItemCase()
GridItemCase()
GridItemCase()
GridItemCase()
GridItemCase()
GridItemCase()
GridItemCase()
GridItemCase()
}
.width("100%")
.height("100%")
// 等分两份
.columnsTemplate("1fr 1fr")
// 列分栏间距
.columnsGap(10)
// 行分栏间距
.rowsGap(10)
.padding(10)
}
}
/**
* 定义内容组件
*/
@Component
struct GridItemCase {
build() {
// 必须放置GridItem组件,不然不会显示宫格
GridItem() {
Row() {
Column() {
Text("内容")
}
.width('100%')
}
.height(200)
.borderRadius(4)
.backgroundColor(Color.Pink)
}
}
}
编译结果:
Scroll 组件
在基本的布局组件 Column/Row/Flex/Stack中不论内容超出与否,皆不会出现滚动条
出现滚动条的组件
- List(列表)
- Grid
- Scroll(滚动条)
- Swiper(轮播)
- WaterFlow(瀑布流)
出现滚动条的前提条件是: 上述组件中的子组件的内容超出了父容器组件的宽度或者高度
使用最基本的Scroll组件出现一个滚动条
先实现基本的布局
示例代码:
@Entry
@Component
struct FlexCase {
// 中间区域高度
@State middleHeight: number = 0
build() {
// 竖向容器
Column() {
// 顶部
Row() {
Text('顶部').width('100%').textAlign(TextAlign.Center)
}
.width('100%')
.height(50)
.backgroundColor(Color.Pink)
// 中间区域
Column() {
Text('要滚动的区域').width('100%').textAlign(TextAlign.Center).fontColor(Color.White)
}
.width('100%')
// 高度为动态计算出 根据视口大小动态计算
.height(this.middleHeight)
.backgroundColor(Color.Gray)
//底部
Row() {
Text('底部').width('100%').textAlign(TextAlign.Center).fontColor(Color.White)
}
.width('100%')
.height(50)
.backgroundColor(Color.Red)
}
.justifyContent(FlexAlign.SpaceBetween)
.width('100%')
.height('100%')
// 监听页面变化(页面初始化也会被调用)
.onAreaChange((old: Area, newArea: Area) => {
// 全局状态设置 高度
this.middleHeight = (newArea.height as number) - 100
})
}
}
编译运行:
实现区域滚动
示例代码:
@Entry
@Component
struct FlexCase {
@State message: string = 'Hello World';
@State middleHeight: number = 0
build() {
Column() {
Row()
.width('100%')
.height(50)
.backgroundColor(Color.Red)
// Scroll List Grid Swiper WaterFlow
Scroll() {
// 有且只能有一个组件
Column() {
ScrollItem()
ScrollItem()
ScrollItem()
ScrollItem()
ScrollItem()
ScrollItem()
ScrollItem()
ScrollItem()
ScrollItem()
ScrollItem()
ScrollItem()
ScrollItem()
ScrollItem()
ScrollItem()
}
}
.width('100%')
.height(this.middleHeight)
.backgroundColor(Color.Orange)
Row()
.width('100%')
.height(50)
.backgroundColor(Color.Blue)
}
.justifyContent(FlexAlign.SpaceBetween)
.width('100%')
.height('100%')
.onAreaChange((old: Area, newArea: Area) => {
this.middleHeight = (newArea.height as number) - 100
})
}
}
@Component
struct ScrollItem {
build() {
Row() {
Text("滚动区域内容")
}
.width('100%')
.height(80)
.backgroundColor(Color.Pink)
.borderRadius(8)
.margin({
top: 20,
bottom: 10
})
.justifyContent(FlexAlign.Center)
}
}
编译运行:
这一期就到这里啦!常用的组件还有很多,这里就不一一列举,大家有兴趣的可以去查看官方文档,去查看更多的组件的使用方式。这一期代码内容比较多,建议大家动起手实操起来。 下一期继续为大家更新组件相关的知识点。