当前位置:   article > 正文

【HarmonyOS应用开发】ArkUI 开发框架-基础篇-第二部分(八)_harmony arkts 类似androidframelayout的布局

harmony arkts 类似androidframelayout的布局

在这里插入图片描述

八、Column&Row组件的使用

概述

一个丰富的页面需要很多组件组成,那么,我们如何才能让这些组件有条不紊地在页面上布局呢?这就需要借助容器组件来实现。

容器组件是一种比较特殊的组件,它可以包含其他的组件,而且按照一定的规律布局,帮助开发者生成精美的页面。容器组件除了放置基础组件外,也可以放置容器组件,通过多层布局的嵌套,可以布局出更丰富的页面。

ArkTS为我们提供了丰富的容器组件来布局页面,本文将以构建登录页面为例,介绍ColumnRow组件的属性与使用。

在这里插入图片描述

1、组件介绍

1.1、布局容器概念

线性布局容器表示按照垂直方向或者水平方向排列子组件的容器,ArkTS提供了ColumnRow容器来实现线性布局。

  • Column表示沿垂直方向布局的容器。
  • Row表示沿水平方向布局的容器。
1.2、主轴和交叉轴概念

在布局容器中,默认存在两根轴,分别是主轴和交叉轴,这两个轴始终是相互垂直的。不同的容器中主轴的方向不一样的。

  • 主轴:Column容器中的子组件是按照从上到下的垂直方向布局的,其主轴的方向是垂直方向;在Row容器中的组件是按照从左到右的水平方向布局的,其主轴的方向是水平方向。

在这里插入图片描述

  • 交叉轴: 与主轴垂直相交的轴线,如果主轴是垂直方向,则交叉轴就是水平方向;如果主轴是水平方向,则交叉轴是垂直方向。

在这里插入图片描述

1.3、属性介绍

了解布局容器的主轴和交叉轴,主要是为了让大家更好地理解子组件在主轴和交叉轴的排列方式。

接下来,我们将详细讲解ColumnRow容器的两个属性justifyContentalignItems

属性名称描述
justifyContent设置子组件在主轴方向上的对齐格式。
alignItems设置子组件在交叉轴方向上的对齐格式。

1. 主轴方向的对齐(justifyContent)
子组件在主轴方向上的对齐使用justifyContent属性来设置,其参数类型是FlexAlignFlexAlign定义了以下几种类型:

  • Start: 元素在主轴方向首端对齐,第一个元素与行首对齐,同时后续的元素与前一个对齐。

在这里插入图片描述

  • Center: 元素在主轴方向中心对齐,第一个元素与行首的距离以及最后一个元素与行尾距离相同。
    在这里插入图片描述
  • End: 元素在主轴方向尾部对齐,最后一个元素与行尾对齐,其他元素与后一个对齐。
    在这里插入图片描述- SpaceBetween: 元素在主轴方向均匀分配弹性元素,相邻元素之间距离相同。 第一个元素与行首对齐,最后一个元素与行尾对齐。

在这里插入图片描述

  • **SpaceAround:**元素在主轴方向均匀分配弹性元素,相邻元素之间距离相同。 第一个元素到行首的距离和最后一个元素到行尾的距离是相邻元素之间距离的一半。
    在这里插入图片描述
  • SpaceEvenly: 元素在主轴方向等间距布局,无论是相邻元素还是边界元素到容器的间距都一样。
    在这里插入图片描述
    2. 交叉轴方向的对齐(alignItems)

子组件在交叉轴方向上的对齐方式使用alignItems属性来设置。
Column容器的主轴是垂直方向,交叉轴是水平方向,其参数类型为HorizontalAlign(水平对齐),HorizontalAlign定义了以下几种类型:

  • Start: 设置子组件在水平方向上按照起始端对齐。
    在这里插入图片描述
  • **Center(默认值):**设置子组件在水平方向上居中对齐。
    在这里插入图片描述- End: 设置子组件在水平方向上按照末端对齐。
    在这里插入图片描述Row容器的主轴是水平方向,交叉轴是垂直方向,其参数类型为VerticalAlign(垂直对齐),VerticalAlign定义了以下几种类型:
  • Top: 设置子组件在垂直方向上居顶部对齐。
    在这里插入图片描述
  • Center(默认值): 设置子组件在竖直方向上居中对齐。
    在这里插入图片描述
  • **Bottom:**设置子组件在竖直方向上居底部对齐。
    在这里插入图片描述
1.4、接口介绍

接下来,我们介绍ColumnRow容器的接口。

容器组件接口
ColumnColumn(value?:{space?: string | number})
RowRow(value?:{space?: string| number})

ColumnRow容器的接口都有一个可选参数space,表示子组件在主轴方向上的间距。效果如下:
在这里插入图片描述

2、组件使用

我们来具体讲解如何高效的使用ColumnRow容器组件来构建这个登录页面。
当我们从设计同学那拿到一个页面设计图时,我们需要对页面进行拆解,先确定页面的布局,再分析页面上的内容分别使用哪些组件来实现。
我们仔细分析这个登录页面。在静态布局中,组件整体是从上到下布局的,因此构建该页面可以使用Column来构建。在此基础上,我们可以看到有部分内容在水平方向上由几个基础组件构成,例如页面中间的短信验证码登录与忘记密码以及页面最下方的其他方式登录,那么构建这些内容的时候,可以在Column组件中嵌套Row组件,继而在Row组件中实现水平方向的布局。

在这里插入图片描述
根据上述页面拆解,在Column容器里,依次是Image、Text、TextInput、Button等基础组件,还有两组组件是使用Row容器组件来实现的,主要代码如下:

@Entry
@Component
export struct LoginPage {
	build() {
		Column() {
			Image($r('app.media.logo'))
				...
			Text($r('app.string.login_page'))
				...
			Text($r('app.string.login_more'))
				...
			TextInput({ placeholder: $r('app.string.account') })
				...
			TextInput({ placeholder: $r('app.string.password') })
				...
			Row() {
				Text($r()) 
				Text($r()) 
			}
			Button($r('app.string.login'), { type: ButtonType.Capsule, stateEffect: true })
				...
			Row() {
				this.imageButton($r())
				this.imageButton($r())
				this.imageButton($r())
			}
			...
		}
		...
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

我们详细看一下使用Row容器的两组组件。
两个文本组件展示的内容是按水平方向布局的,使用两端对齐的方式。这里我们使用Row容器组件,并且需要配置主轴上(水平方向)的对齐格式justifyContentFlexAlign.SpaceBetween(两端对齐)。

Row() {
	Text($r()) 
	Text($r()) 
}
.justifyContent(FlexAlign.SpaceBetween)
.width('100%')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

其他登录方式的三个按钮也是按水平方向布局的,同样使用Row容器组件。这里按钮的间距是一致的,我们可以通过配置可选参数space来设置按钮间距,使子组件间距一致。

Row({ space: CommonConstants.LOGIN_METHODS_SPACE }) {
	this.imageButton($r())
	this.imageButton($r())
	this.imageButton($r())
}
  • 1
  • 2
  • 3
  • 4
  • 5

九、List组件和Grid组件的使用

1、简介

在我们常用的手机应用中,经常会见到一些数据列表,如设置页面、通讯录、商品列表等。下图中两个页面都包含列表,“首页”页面中包含两个网格布局,“商城”页面中包含一个商品列表。
在这里插入图片描述上图中的列表中都包含一系列相同宽度的列表项,连续、多行呈现同类数据,例如图片和文本。常见的列表有线性列表(List列表)和网格布局(Grid列表):
在这里插入图片描述为了帮助开发者构建包含列表的应用,ArkUI提供了List组件和Grid组件,开发者使用List和Grid组件能够很轻松的完成一些列表页面。

2、List组件的使用

2.1、List组件简介

List是很常用的滚动类容器组件,一般和子组件ListItem一起使用,List列表中的每一个列表项对应一个ListItem组件。
在这里插入图片描述

2.2、使用ForEeach渲染列表

列表往往由多个列表项组成,所以我们需要在List组件中使用多个ListItem组件来构建列表,这就会导致代码的冗余。使用循环渲染(ForEach)遍历数组的方式构建列表,可以减少重复代码,示例代码如下:

@Entry
@Component
struct ListDemo {
private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

build() {
	Column() {
		List({ space: 10 }) {
			ForEach(this.arr, (item: number) => {
				ListItem() {
					Text(`${item}`)
						.width('100%')
						.height(100)
						.fontSize(20)
						.fontColor(Color.White)
						.textAlign(TextAlign.Center)
						.borderRadius(10)
						.backgroundColor(0x007DFF)
					}
				}, item => item)
			}
		}
		.padding(12)
		.height('100%')
		.backgroundColor(0xF1F3F5)
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

效果图如下:

在这里插入图片描述

2.3、设置列表分割线

List组件子组件ListItem之间默认是没有分割线的,部分场景子组件ListItem间需要设置分割线,这时候您可以使用List组件的divider属性。divider属性包含四个参数:

  • strokeWidth: 分割线的线宽。
  • color: 分割线的颜色。
  • startMargin: 分割线距离列表侧边起始端的距离。
  • endMargin: 分割线距离列表侧边结束端的距离。
    在这里插入图片描述
2.4、List列表滚动事件监听

List组件提供了一系列事件方法用来监听列表的滚动,您可以根据需要,监听这些事件来做一些操作:

  • onScroll: 列表滑动时触发,返回值scrollOffset为滑动偏移量,scrollState为当前滑动状态。
  • onScrollIndex: 列表滑动时触发,返回值分别为滑动起始位置索引值与滑动结束位置索引值。
  • onReachStart: 列表到达起始位置时触发。
  • onReachEnd: 列表到底末尾位置时触发。
  • onScrollStop 列表滑动停止时触发。

使用示例代码如下:

List({ space: 10 }) {
	ForEach(this.arr, (item) => {
		ListItem() {
			Text(`${item}`)
				...
		}
	}, item => item)
}
.onScrollIndex((firstIndex: number, lastIndex: number) => {
	console.info('first' + firstIndex)
	console.info('last' + lastIndex)
})
.onScroll((scrollOffset: number, scrollState: ScrollState) => {
	console.info('scrollOffset' + scrollOffset)
	console.info('scrollState' + scrollState)
})
.onReachStart(() => {
	console.info('onReachStart')
})
.onReachEnd(() => {
	console.info('onReachEnd')
})
.onScrollStop(() => {
	console.info('onScrollStop')
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
2.5、设置List排列方向

List组件里面的列表项默认是按垂直方向排列的,如果您想让列表沿水平方向排列,您可以将List组件的listDirection属性设置为Axis.Horizontal。listDirection参数类型是Axis,定义了以下两种类型:

  • Vertical(默认值): 子组件ListItem在List容器组件中呈纵向排列。
    在这里插入图片描述

  • Horizontal: 子组件ListItem在List容器组件中呈横向排列。
    在这里插入图片描述

3、Grid组件的使用

3.1、Grid组件简介

Grid组件为网格容器,是一种网格列表,由“行”和“列”分割的单元格所组成,通过指定“项目”所在的单元格做出各种各样的布局。Grid组件一般和子组件GridItem一起使用,Grid列表中的每一个条目对应一个GridItem组件。

在这里插入图片描述

3.2、使用ForEach渲染网格布局

List组件一样,Grid组件也可以使用ForEach来渲染多个列表项GridItem,我们通过下面的这段示例代码来介绍Grid组件的使用。

@Entry
@Component
struct GridExample {
	// 定义一个长度为16的数组
	private arr: string[] = new Array(16).fill('').map((_, index) => `item ${index}`);

	build() {
		Column() {
			Grid() {
				ForEach(this.arr, (item: string) => {
					GridItem() {
						Text(item)
							.fontSize(16)
							.fontColor(Color.White)
							.backgroundColor(0x007DFF)
							.width('100%')
							.height('100%')
							.textAlign(TextAlign.Center)
					}
				}, item => item)
			}
			.columnsTemplate('1fr 1fr 1fr 1fr')
			.rowsTemplate('1fr 1fr 1fr 1fr')
			.columnsGap(10)
			.rowsGap(10)
			.height(300)
		}
		.width('100%')
		.padding(12)
		.backgroundColor(0xF1F3F5)
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

示例代码中创建了16个GridItem列表项。同时设置columnsTemplate的值为’1fr 1fr 1fr 1fr’,表示这个网格为4列,将Grid允许的宽分为4等分,每列占1份;rowsTemplate的值为’1fr 1fr 1fr 1fr’,表示这个网格为4行,将Grid允许的高分为4等分,每行占1份。这样就构成了一个4行4列的网格列表,然后使用columnsGap设置列间距为10vp,使用rowsGap设置行间距也为10vp。示例代码效果图如下:
在这里插入图片描述
上面构建的网格布局使用了固定的行数和列数,所以构建出的网格是不可滚动的。然而有时候因为内容较多,我们通过滚动的方式来显示更多的内容,就需要一个可以滚动的网格布局。我们只需要设置rowsTemplatecolumnsTemplate中的一个即可。

将示例代码中GridItem的高度设置为固定值,例如100;仅设置columnsTemplate属性,不设置rowsTemplate属性,就可以实现Grid列表的滚动:

Grid() {
	ForEach(this.arr, (item: string) => {
		GridItem() {
			Text(item)
				.height(100)
				...
		}
	}, item => item)
}
.columnsTemplate('1fr 1fr 1fr 1fr')
.columnsGap(10)
.rowsGap(10)
.height(300)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

此外,GridList一样也可以使用onScrollIndex来监听列表的滚动。

四、Tabs组件的使用

1、概述

在我们常用的应用中,经常会有视图内容切换的场景,来展示更加丰富的内容。比如下面这个页面,点击底部的页签的选项,可以实现“首页”和“我的”两个内容视图的切换。

在这里插入图片描述
ArkUI开发框架提供了一种页签容器组件Tabs,开发者通过Tabs组件可以很容易的实现内容视图的切换。页签容器Tabs的形式多种多样,不同的页面设计页签不一样,可以把页签设置在底部、顶部或者侧边。

在这里插入图片描述本文将详细介绍Tabs组件的使用。

2、Tabs组件的简单使用

Tabs组件仅可包含子组件TabContent,每一个页签对应一个内容视图即TabContent组件。下面的示例代码构建了一个简单的页签页面:

@Entry
@Component
struct TabsExample {
	private controller: TabsController = new TabsController()

	build() {
		Column() {
			Tabs({ barPosition: BarPosition.Start, controller: this.controller }) {
				TabContent() {
					Column().width('100%').height('100%').backgroundColor(Color.Green)
				}
				.tabBar('green')

				TabContent() {
					Column().width('100%').height('100%').backgroundColor(Color.Blue)
}
				.tabBar('blue')

				TabContent() {
					Column().width('100%').height('100%').backgroundColor(Color.Yellow)
				}
				.tabBar('yellow')

				TabContent() {
					Column().width('100%').height('100%').backgroundColor(Color.Pink)
				}
				.tabBar('pink')
			}
			.barWidth('100%') // 设置TabBar宽度
			.barHeight(60) // 设置TabBar高度
			.width('100%') // 设置Tabs组件宽度
			.height('100%') // 设置Tabs组件高度
			.backgroundColor(0xF5F5F5) // 设置Tabs组件背景颜色
		}
		.width('100%')
		.height('100%')
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

效果图如下:
在这里插入图片描述
上面示例代码中,Tabs组件中包含4个子组件TabContent,通过TabContenttabBar属性设置TabBar的显示内容。使用通用属性widthheight设置了Tabs组件的宽高,使用barWidthbarHeight设置了TabBar的宽度和高度。

在这里插入图片描述

说明

  • TabContent组件不支持设置通用宽度属性,其宽度默认撑满Tabs父组件。
  • TabContent组件不支持设置通用高度属性,其高度由Tabs父组件高度与TabBar组件高度决定。

3、设置TabBar布局模式

因为Tabs的布局模式默认是Fixed的,所以Tabs的页签是不可滑动的。当页签比较多的时候,可能会导致页签显示不全,将布局模式设置为Scrollable的话,可以实现页签的滚动。

Tabs的布局模式有Fixed(默认)和Scrollable两种:

  • BarMode.Fixed: 所有TabBar平均分配barWidth宽度(纵向时平均分配barHeight高度),页签不可滚动,效果图如下:
    在这里插入图片描述
  • BarMode.Scrollable: 每一个TabBar均使用实际布局宽度,超过总长度(横向TabsbarWidth,纵向TabsbarHeight)后可滑动。
    在这里插入图片描述
  • 当页签比较多的时候,可以滑动页签,下面的示例代码将barMode设置为BarMode.Scrollable,实现了可滚动的页签:
@Entry
@Component
struct TabsExample {
	private controller: TabsController = new TabsController()

	build() {
		Column() {
			Tabs({ barPosition: BarPosition.Start, controller: this.controller }) {
				TabContent() {
					Column()
						.width('100%')
						.height('100%')
						.backgroundColor(Color.Green)
				}
				.tabBar('green')

				TabContent() {
					Column()
						.width('100%')
						.height('100%')
						.backgroundColor(Color.Blue)
				}
				.tabBar('blue')

				...

			}
			.barMode(BarMode.Scrollable)
			.barWidth('100%')
			.barHeight(60)
			.width('100%')
			.height('100%')
		}
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

4、设置TabBar位置和排列方向

Tabs组件页签默认显示在顶部,某些场景下您可能希望Tabs页签出现在底部或者侧边,您可以使用Tabs组件接口中的参数barPosition设置页签位置。此外页签显示位置还与vertical属性相关联,vertical属性用于设置页签的排列方向,当vertical的属性值为false(默认值)时页签横向排列,为true时页签纵向排列。

barPosition的值可以设置为BarPosition.Start(默认值)和BarPosition.EndBarPosition.Start

vertical属性方法设置为false(默认值)时,页签位于容器顶部。

Tabs({ barPosition: BarPosition.Start }) {
	...
}
.vertical(false) 
.barWidth('100%') 
.barHeight(60)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

效果图如下:
在这里插入图片描述
vertical属性方法设置为true时,页签位于容器左侧。

Tabs({ barPosition: BarPosition.Start }) {
	...
}
.vertical(true) 
.barWidth(100) 
.barHeight(200) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

效果图如下:

在这里插入图片描述
BarPosition.End
vertical属性方法设置为false时,页签位于容器底部。

Tabs({ barPosition: BarPosition.End }) {
	...
}
.vertical(false) 
.barWidth('100%') 
.barHeight(60)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

效果图如下:
在这里插入图片描述
vertical属性方法设置为true时,页签位于容器右侧。

Tabs({ barPosition: BarPosition.End}) {
	...
}
.vertical(true) 
.barWidth(100) 
.barHeight(200)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

效果图如下:
在这里插入图片描述

5、自定义TabBar样式

TabBar的默认显示效果如下所示:
在这里插入图片描述

往往开发过程中,UX给我们的设计效果可能并不是这样的,比如下面的这种底部页签效果:
在这里插入图片描述
TabContenttabBar属性除了支持string类型,还支持使用@Builder装饰器修饰的函数。您可以使用@Builder装饰器,构造一个生成自定义TabBar样式的函数,实现上面的底部页签效果,示例代码如下:

@Entry
@Component
struct TabsExample {
	@State currentIndex: number = 0;
	private tabsController: TabsController = new TabsController();

@Builder TabBuilder(title: string, targetIndex: number, selectedImg: Resource, normalImg: Resource) {
		Column() {
			Image(this.currentIndex === targetIndex ? selectedImg : normalImg)
				.size({ width: 25, height: 25 })
			Text(title)
				.fontColor(this.currentIndex === targetIndex ? '#1698CE' : '#6B6B6B')
			}
			.width('100%')
			.height(50)
			.justifyContent(FlexAlign.Center)
			.onClick(() => {
				this.currentIndex = targetIndex;
				this.tabsController.changeIndex(this.currentIndex);
	})
}

	build() {
		Tabs({ barPosition: BarPosition.End, controller: this.tabsController }) {
			TabContent() {
				Column().width('100%').height('100%').backgroundColor('#00CB87')
			}
			.tabBar(this.TabBuilder('้ฆ–้กต', 0, $r('app.media.home_selected'), $r('app.media.home_normal')))

			TabContent() {
				Column().width('100%').height('100%').backgroundColor('#007DFF')
			}
			.tabBar(this.TabBuilder('ๆ‘็', 1, $r('app.media.mine_selected'), $r('app.media.mine_normal')))
			}
			.barWidth('100%')
			.barHeight(50)
			.onChange((index: number) => {
this.currentIndex = index;
		})
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

示例代码中将barPosition的值设置为BarPosition.End,使页签显示在底部。使用@Builder修饰TabBuilder函数,生成由ImageText组成的页签。同时也给Tabs组件设置了TabsController控制器,当点击某个页签时,调用changeIndex方法进行页签内容切换。

最后还需要给Tabs添加onChange事件,Tab页签切换后触发该事件,这样当我们左右滑动内容视图的时候,页签样式也会跟着改变。

案例代码下载
常用组件与布局

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/238545
推荐阅读
相关标签
  

闽ICP备14008679号