上一节我们实现了仿微信的好友列表,那么在微信的主界面,其底部固定放着一排页签栏,点击某个页面,即可迅速切换到对应的界面板块。并且当前页的底部页签高亮显示,方便用户知晓当前处于哪个板块。鸿蒙App采用Tabs组件实现页签栏,使用起来十分灵活。下面详细介绍如何使用Tabs组件实现仿微信App的底部页签栏。
1、底部页签的整体框架
鸿蒙App采用声明式UI,使得代码拿不到组件的实例,可是有时又需要让组件执行某种动作,比如页签组件Tabs可能会切换到指定页面,像这种切换操作要求提前给Tabs绑定控制器对象,方便后面由控制器执行具体的切换操作。比如下面代码就声明了一个Tabs组件的控制器对象:
tabsController: TabsController = new TabsController()
声明式UI设置Tabs组件的属性有两种途径,一种是在Tabs的构造方法中传入待设置的属性,主要包括下列三种初始属性:
barPosition:页签栏的位置。为BarPosition.Start表示放在页面开头,为BarPosition.End表示放在页面末尾。
index:设置当前页签的序号。默认为0表示位于第一个页签。
controller:设置Tabs组件的控制器对象。
设置Tabs属性的另一种途径是调用对应的方法,常用的Tabs属性设置方法如下:
vertical:设置页面的布局方向。默认false表示水平布局,为true表示垂直布局。
barMode:设置页签栏的滑动模式。默认BarMode.Fixed表示固定,为BarMode.Scrollable表示允许滑动。
barWidth:设置页签栏的宽度。
barHeight:设置页签栏的高度。
animationDuration:设置页签切换动画的时长,单位毫秒。
onChange:设置页签的切换事件,可在此填入切换页签时需要指定的代码逻辑。
下面是在ArkUI中显示底部页签的Tabs组件框架代码:
// barPosition取值Start表示放在开头,取值End表示放在末尾
Tabs({ barPosition: BarPosition.End, index: this.current, controller: this.tabsController }) {
// 这里暂时省略内部组件的代码
}
.vertical(false) // 是否垂直布局。默认false表示水平布局
.barMode(BarMode.Fixed) // 页签栏模式。默认Fixed表示固定,为Scrollable表示允许滑动
.barWidth('100%') // 页签栏的宽度
.barHeight(70) // 页签栏的高度
.animationDuration(0) // 页签切换动画的时长
.onChange((index: number) => {
this.current = index
})
2、自定义单个页签的布局
ArkUI默认的单个页签风格很单调,仅仅提供页签文字罢了,缺少微信底部页签的丰富样式。为了给页签增加包含图标和文字在内的高亮效果,需要自己定义单个页签的布局内容。
自定义的页签布局以“@Builder”打头,其后就像编写普通的方法代码那样,包括方法名称、方法参数、方法代码等等。常见的页签高亮特效会区分背景、图标、文字颜色和字号样式,可以采用Stack容器作为单个页签的根布局,先放入一张背景图片,再放入Column容器包裹的前景图标和前景文字。注意给当前页和其他页分别设置不同的背景、图标、文字颜色和字号样式。
下面是一个自定义页签的布局代码例子:
// 自定义单个页签的布局内容。需传入各页签的序号、名称、高亮图标、灰显图标
@Builder tabBuilder(index: number, name: string, selectedIcon: Resource, normalIcon: Resource) {
Stack() {
// 区分当前页和其他页的背景,当前页背景高亮,其他页背景灰显
Image(this.current === index ? $r('app.media.tab_bg_selected'): $r('app.media.tab_bg_normal'))
.width('100%').height('100%').objectFit(ImageFit.Fill)
Column() {
// 区分当前页和其他页的图标,当前页图标高亮,其他页图标灰显
Image(this.current === index ? selectedIcon : normalIcon).width(40).height(40)
Text(name)
// 区分当前页和其他页的文字颜色,当前页字色高亮,其他页字色灰显
.fontColor(this.current === index ? this.selectedColor : this.normalColor)
.fontSize(15)
// 区分当前页和其他页的字号样式,当前页字号加粗,其他页字号正常
.fontWeight(this.current === index ? FontWeight.Bold : FontWeight.Normal)
.lineHeight(22)
.margin({ top: 0, bottom: 5 })
}.width('100%').padding(5)
}.width('100%')
}
3、给页签栏分配对应的页签布局
有了Tabs组件框架之后,再往内部填充具体的页签元素信息。填充时既能采取ForEach的循环语句,也能逐个添加单个页签。考虑到页签栏内部的页签数量不会很多,在代码中逐个添加页签项会更方便。单个页签元素的组件以TabContent开头,且TabContent组件只能有唯一的下级节点。
TabContent组件通过tabBar方法传入前面第二步自定义的页签布局,注意引用自定义页签布局时,依次传入该布局所需的各个输入参数,用来设置具体的高亮和灰显效果。以仿微信主界面的三个页签为例,可在Tabs组件内部分别填入名叫“好友”、“群聊”和“我的”这三个TabContent内容。
下面是给底部页签填充三个自定义页签的布局代码:
TabContent() {
Column() {
// 这里省略好友页面的布局内容
}.width('100%').height('100%').justifyContent(FlexAlign.End)
}.tabBar(this.tabBuilder(0, '好友', $r('app.media.tab_first_pressed'),
$r('app.media.tab_first_normal')))
TabContent() {
Column() {
// 这里省略群聊页面的布局内容
}.width('100%').height('100%').justifyContent(FlexAlign.End)
}.tabBar(this.tabBuilder(1, '群聊', $r('app.media.tab_second_pressed'),
$r('app.media.tab_second_normal')))
TabContent() {
Column() {
// 这里省略我的页面的布局内容
}.width('100%').height('100%').justifyContent(FlexAlign.End)
}.tabBar(this.tabBuilder(2, '我的', $r('app.media.tab_third_pressed'),
$r('app.media.tab_third_normal')))
综合以上的页签布局代码,实现的仿微信主界面的底部页签如下:
下一篇文章会介绍如何实现微信个人资料界面的昵称修改弹窗。