大家好!我是黑臂麒麟,一位6年的前端;
随着鸿蒙4.0
的发布。鸿蒙社区不断壮大,且市场对harmonyOS
应用认可度越来越高。很多公司开始对鸿蒙应用开发
越来越重视。
之前想入坑鸿蒙,一直犹豫未下定决心学习。这次不再等待,开始系统学习起来。
此系列文章只做harmonyOS
学习记录,大家如有兴趣,希望文章对您有所帮助;
if you’re change the world, you’re workingon important things. you’re excited to get up in the norning.
一、常用基础组件
1.基础组件
简单列举常用的及含义,掌握了以下按钮可以解决日常简单场景需求。其他在使用时查询ArkTS
的API文档即可。
组件 | 含义 |
---|---|
Text() | 显示一段文本的组件。 |
Image() | 图片组件,支持本地图片和网络图片的渲染展示 |
TextInput() | 单行文本输入框组件。 |
Button() | 按钮 |
Blank | 空白填充组件,在容器主轴方向上,空白填充组件具有自动填充容器空余部分的能力。仅当父组件为Row/Column时生效。 |
LoadingProgress | 显示加载进展 |
… |
2.文本样式
ArkTS
的样式以驼峰命名方式,这里以Text
组件为例:
名称 | 参数类型 | 描述 |
---|---|---|
fontColor | ResourceColor | 设置文本颜色 |
fontSize | Length or Resource | 设置文本颜色 |
fontStyle | FontStyle | 设置文本的字体样式。默认值:FontStyle.Normal。 |
fontWeight | numbe or FontWeight or string | 设置文本的字体粗细,number类型取值[100, 900],取值间隔为100,默认为400,取值越大,字体越粗。string类型仅支持number类型取值的字符串形式,例如“400”,以及“bold”、“bolder”、“lighter”、“regular”、“medium”,分别对应FontWeight中相应的枚举值。默认值:FontWeight.Normal。 |
下面代码是两个Text组件,分别是默认样式和设置了文本样式的对比。
@Entry@Componentstruct Index { @State message: string = 'Hello World'; @State myText: string = 'World'; build() { Row() { Column(){ Text('ArkTs') Text('ArkTs') .fontColor(Color.Blue) .fontSize(40) .fontWeight(FontWeight.Bold) .fontFamily('Arial') } } .justifyContent(FlexAlign.Center) .backgroundColor(0xF1F3F5) .width('100%') .height('100%') }}
以上ArkTs代码的样式使用驼峰格式
;其他组件的样式也是一样。使用时查阅具体用法。
3.Image
这里着重说一下Image的图片地址的引入方式
,方式如下:
Image(src: string|PixelMap|Resource)
(1).使用string数据加载网络图片
Image(‘https://www.example.com/xxx.png’)
这里要注意Image
在使用网络图片的时候,需要要在module.json5
文件中声明网络访问权限
// module.json5{ "module": { "requestPermissions": [ "name": "ohos.permisssion.INTERNET" ] }}
(2).使用PixelMap
数据加载图片
Image(pixelMapObject)
(3)使用Resource数据加载图片
Image($r('app.media.logo'))
上面的Resource是一种资源引入类型。会在下面详细描述。
4.使用资源引用类型
Resource
是资源引用类型,用于设置组件属性的值。ArkTs文档推荐优先使用Resource类型
,将资源文件(字符串、图片、音频等)统一存放于resources
目录下,便于开发者统一维护。同事系统可以根据当前配置加载合适资源,例如,开发者根据屏幕尺寸呈现不同的布局效果,或根据语言提供不同的字符串。
已上面Text组件代码为例:
Text('ArkTs') .fontColor(Color.Blue) .fontSize(40) .fontWeight(FontWeight.Bold) .fontFamily('Arial')
(1).对元素内文本字符串的管理;
可以将这些编码写到entry/src/main/resources下的资源文件中。
在string.json中定义Button显示的文本
就个人而言,不太喜欢这种方式相对于前端喜欢而言。
在float.json
中定义Text
的字体样式。
在color.json中定义Text的字体颜色。
然后再Text组件通过$r('app.type.name)
的形式引用应用资源。app带表应用内resources目录中定义的资源;type
代表资源类型(或资源的存放位置),可以取“color”,“float”、“string”、“plural”、“media”; 以上几种是固定的,不支持自定义命名文件引用。name代表资源命名,由开发者定义资源时确定的。
Text($r('app.string.Index_Text')) .fontColor($r('app.color.Text_color')) .fontSize($r('app.float.Text_fontSize')) .fontWeight(FontWeight.Bold) .fontFamily($r('app.float.Text_fontFamily'))
以上是简单的描述Resource
引用方式,后面回单独出一期深入研究的Resource
引入文章。
二、布局组件
前端常用布局方式header、side、main、footer
等标签,还有布局样式flex
、grid
等,在ArkTs
常用布局组件有一下几种:
组件 | 描述 |
---|---|
Column | 垂直方向布局的容器 |
Row | 水平方向布局的容器 |
List | 列表容器 |
Grid | 网格容器 |
Tabs | 页签容器 |
Swiper | 滑块视图容器 |
Scroll | 可滑动的容器 |
这里说一下List
,Grid
,Tabs
,Column
、Row
使用方法,Swiper、Scroll布局组件相对简单详见Api文档。有点类似小程序的类似组件。
1. Column&Row
布局容器概念
线性布局容器表示垂直方向或者水平方向排列子组件的容器,ArkTs
提供了Column
和Row
容器来实现线性布局。
主轴和交叉轴概念
在布局容器中,默认存在两根轴,分别是主轴和交叉轴,这两个轴始终是相互垂直的。不同的容器中主轴的方向不一样的。
主轴:在Column容器中的子组件是按照从上到下
的垂直方向布局,其主轴的方向是垂直方向;在Row容器中的组件时按照从左到右
的水平方向布局的,其主轴的方向时水平方向。下图时Column&Row容器交叉轴
属性
Column&Row容器的两个属性justifyContent和alignItems,类似CSS的flex或Grid的justify-content和align-item。这样容易让我们前端快速理解。
这里注意一下它们的属性值都要首字母大写
。
属性名称 | 描述 |
---|---|
justifyContent | 设置子组件在主轴方向上的对齐格式 |
alignItems | 设置子组件在交叉轴方向上的对齐格式 |
主轴方向的对其(justifyContent)
子组件在主轴方向上的使用jusifyContent
属性来设置,其参数类型时FlexAlign
。它有一下几种类型:
属性值 | 描述 |
---|---|
Start | 主轴方向首端对齐,第一个元素与行首对齐,同时后续的元素与前一个对齐 |
Center | 主轴方向中心对齐,第一个元素与行首的距离以及最后一个元素与行尾距离相同 |
End | 主轴方向尾部对齐,最后一个元素与行尾对齐,其他元素与后一个对齐 |
SpaceBetween | 主轴方向均匀分配弹性元素,相邻元素之间距离相同。 第一个元素与行首对齐,最后一个元素与行尾对齐 |
SpaceAround | 轴方向均匀分配弹性元素,相邻元素之间距离相同。 第一个元素到行首的距离和最后一个元素到行尾的距离是相邻元素之间距离的一半 |
SpaceEvenly | 主轴方向等间距布局,无论是相邻元素还是边界元素到容器的间距都一样 |
Start
Center
End
SpaceBetween
SpaceAround
SpaceEvenly
交叉中方向对齐(alignItems)
Column容器的主轴时垂直方向,交叉轴是水平方向,其参数类型为HorizontalAlign
(水平对齐),HorizontalAlign
定义了一下几个类型;
属性值 | 描述 |
---|---|
Start | 水平方向上按照起始端对齐 |
Center | 水平方向上居中对齐 |
End | 水平方向上按照末端对齐 |
start
Centent
End
Row容器的主轴是水平方向,交叉轴是垂直方向,其参数类型为VerticalAlign(垂直对其),VerticalAlign定义了一下几种类型:
|属性值|描述|
|–|–|
|Top|垂直方向上居顶部对齐|
|Center|竖直方向上居中对齐|
|Bottom|竖直方向上居底部对齐|
Top
Center
Bottom
接口介绍
Column&Row都课接收一个参数space
,表示子组件在主轴上的间距;
@Entry@Componentstruct Index { @State TextArr: Array<string> = ["Image", "Text", "TextInput", "Button"] build() { Column({space: 30}) { // 这里设置子元素主轴上的间距 ForEach(this.TextArr, (item: string)=> { // 利用ForEach渲染我们的字符串数组 Row(){ Text(item) } .width('80%') .height('100vp') .backgroundColor('#99b2df') .border({ width: 5, color: '#8aa7da', style: BorderStyle.Solid }) .justifyContent(FlexAlign.Center) }) } .justifyContent(FlexAlign.Start) .backgroundColor('#bdd7ee') .width('100%') .height('100%') }}
渲染出来的效果:
3. List使用
简介
使用频率很高的组件,需要配合ListItem
子组件一起使用,列表每项对应一个ListItem
组件
使用ForEach渲染
渲染多时,可以使用ForEach来循环渲染我们的列表项;
@Entry@Componentstruct Index { private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] build() { Column({space: 30}) { List({space: 10}) { ForEach(this.arr, (item: number)=> { ListItem(){ Text(`${item}`) .width('100%') .height(100) .fontSize(20) .fontColor(Color.White) .textAlign(TextAlign.Center) .backgroundColor(0x007DFF) } }, item => item) } } .padding(12) .height('100%') .backgroundColor(0xF1F3F5) }}
设置分割线
这里如有需求可以给list组件可以使用divider
属性给ListItem
设置分割线。有四个参数:
List({space: 50}) { ForEach(this.arr, (item: number)=> { ListItem(){ Text(`${item}`) } }, item => item)}.divider({ strokeWidth: 5, color: '#d8d8d8', startMargin: 20, endMargin: 20, })
列表滚动事件监听
List滚动监听事件和前端监听Scroll监听时间方法很像:
onScroll
: 滑动触发,返回scrollOffset
为滑动偏移量,scrollState
为当前滑动状态。onScrollIndex
: 滑动时触发,分别返回滑动起始索引值与滑动结束索引值。onReachStart
: 列表到达起始位置时触发。onReachEnd:
列表到底末尾位置触发。onScrollStrop
: 列表滑动结束时触发。利用这些时间监听,并可以在
log
面板中打印出我们想要的滑动数据; 设置List排列方向
List
组件排列可以垂直方向和水平方向排列,默认是垂直方向排列。如果想设置List
为水平方向,可以使用listDiretion
属性为Axis.Horizontal即可。
4. Grid
简介
如果前端学过css的grid布局模式,那大家一定不会对Grid
组件布局陌生,接下来学习如何使用Grid
网格布局组件。
使用
Grid
组件是由“行”和“列”分割的单元格组成。Grid
一般和GridItem
一起使用。
@Entry@Componentstruct GridPage { private arr: string[] = new Array(9).fill('').map((_, index) => `item ${index + 1}`) 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: string) => item) } .columnsTemplate('1fr 1fr 1fr') .rowsTemplate('1fr 1fr 1fr') .columnsGap(10) .rowsGap(10) .height(300) } .width('100%') .padding(12) .backgroundColor(0xF1F3F5) }}
这里我们同样跟List一样使用ForEach
遍历出的数组,可以看到我们设置columnsTemplate
属性垂直方向配置3等分个1fr
,同样纵向rowsTemplate
也是3等分的1fr
,1fr
代表所占Grid等分个数。columnGap
和rowGap
分别设置垂直和纵向元素之间的间距。这里分别设置了 10vp
。
5. Tabs
概述
Tabs
是我们常用的做视图切换的常用布局组件。如“底部页签”,“顶部标签”,平板的“侧边页签”等。
使用
Tabs
组件仅含子组件TabContent,每一个页签对应内容视图即TabContent组件。
结合之前我们写的List
和Grid
的组件,我们编写一个简单的Tabs
布局
import Home from '../view/Home';import GridPage from '../view/GridPage'@Entry@Componentstruct Index { private controller: TabsController = new TabsController(); build() { Column() { Tabs() { TabContent() { Home() } .tabBar('List') TabContent() { GridPage() } .tabBar('Grid') } .barWidth('100%') // 设置TabBar宽度 .barHeight('60') // 设置TabBar高度 .width('100%') .height('100%') .backgroundColor(0xF5F5F5) } .width('100%') .height('100%') }}
展示后的效果
上面代码,通过属性width
和height
设置了Tabs
组件的宽高,使用TabWidth
和BarHeight
设置了TabBar
的宽度和高度。
设置TabBar布局属性
Tabs
布局模式默认Fixed的,不支持滑动。如果页签过多会可能导致显示不全,讲布局模式设置为Scrollable的话,可以实现页签的滚动。
布局属性 | 描述 | 属性值 |
---|---|---|
barMode | Tabs的布局模式 | BarMode.Fixed (默认):所有TabBar平均分配barWidth宽度。 BarMode.Scrollable: 每个TabBar使用实际宽度,超过总长度后可滑动。 |
barPosition | 设置TabBar位置和排列方向 | BarPosition.Start,vertical属性为false(默认值)时,页签在顶部.vertical属性为true时,位于容器左侧。 BarPosition.End, vertical属性为false时,位于容器底部。vertical属性为true时,位于容器右侧。 |
自定义TabBar样式
如果需要自定义TabBar
, 需要通过@Builder装饰器的函数。构造一个生成自定义TabBar样式的函数,我们来实现上面底部页签效果:
import Home from '../view/Home';import GridPage from '../view/GridPage'@Entry@Componentstruct Index { private tabsController: TabsController = new TabsController(); @State currentIndex: number = 0; @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() { Column() { Tabs({barPosition: BarPosition.End, controller: this.tabsController}) { TabContent() { Home() } .tabBar(this.TabBuilder('List', 0, $r('app.media.home_selected'), $r('app.media.home_normal'))) TabContent() { GridPage() } .tabBar(this.TabBuilder('List', 1, $r('app.media.mine_selected'), $r('app.media.mine_normal'))) } .vertical(false) .barWidth("100%") // 设置TabBar宽度 .barHeight(60) // 设置TabBar高度 .width('100%') .height('100%') .backgroundColor(0xF5F5F5) .onChange((index: number) => { this.currentIndex = index; }) } .width('100%') .height('100%') }}
渲染后效果:
将barPosition
的值设置为BarPosition.End
,使页签显示在底部。使用@Builder自定义TabBuilder函数,生成由Image和Text组成的页签。同时也给Tabs
组件设置了TabsController
控制器,当点击某个页签时,调用changeIndex
方法进行页签内容切换。
最后在Tabs添加onChange事件。切换时,把当前最近Index
赋给currentIndex保存起来。
参考
华为开发者联盟官网开发者基础课程
结语
至此,本篇文章的内容结束了。文章有不对或不完整的地方,望多指点;
望更多小伙伴们加入harmonyOS开发大家庭,壮大生态圈,让鸿蒙更强大更好。
如果对你学习有所帮助,还请点赞、评论、收藏、关注、分享;
希望可爱你动动小手关注订阅,一起进步期待你的三连支持;