设置组件导航
1. Navigation组件
1.1 基础概念
Vavigation组件是由路由导航的根视图容器,一般作为Page页面的根容器使用,可以实现路由进行切换。
在使用Navigation组件时,若设置Navigation组件的mode属性为NavigationMode.Auto,那么当设备宽度大于520vp时,Navigation组件会采用分栏模式,反之采用单页面模式
1.2 组件介绍
- 标题栏
标题栏在界面顶部,用于呈现界面名称和操作入口,Navigation组件通过titleMode属性设置标题栏模式。
- Mini模式:普通标题栏,用于一级页面不需要团出标题的场景
Navigition() {
...
}
.titleMode(NavigationTitleMode.Mini)
- Full模式:强调行标题栏,用于一级页面需要突出标题的场景
Navigition() {
...
}
.titleMode(NavigationTitleMode.Full)
- 也可以通过设置Navigation的hideTitleBar为true属性,来隐藏标题栏
- 菜单栏
菜单栏位于Navigation组件的右上角,不设置时默认不会进行显示。开发者可以通过menus属性进行设置。menus支持Array和CustomBuilder两种参数类型。在使用Array类型时竖屏最多支持显示3个图标,横屏最多支持显示5个图标,多余的图标会被放入自动生成的更多图标。
let menuItem1:NavigationMenuItem={'value': '','icon': './image/ic_search.svg','action':()=>{}};
let menuItem2 :NavigationMenuItem={'value': '','icon': './image/ic_add.svg','action':()=>{}};
Navigation(){
...
}
.menus([menuItem1,menuItem2,menuItem2])
- value表示在菜单栏单个选项的文本
- icon表示显示在菜单栏单个选项的图标资源目录
- action参数为当前选项被选中的事件回调函数
- 工具栏
工具栏位于Navigation组件的底部,开发者可以通过toolbarConfiguration属性进行设置。该属性需要传入一个Toolbaritem构成的数组。
let toolItem:ToolbarItem ={ 'value': '','icon': './image/ic_public_highlights.svg','action':()=>{}};
Navigation(){
...
}
.toolbarConfiguration(tooBar)
- value表示在工具栏单个选项的文本
- icon配置工具栏选项的图标
- action配置工具栏选型被选中时的回调
1.3 模块内页面切换
在使用Navigation组件中,非常重要的一个点就是依靠Navigation组件提供的组件级路由能力实现更加自然流畅的转场体验,而这就需要依靠路由栈提供的系列方法。
push系列方法:将指定的页面栈数据信息入栈。
- pushPath(info:NavPathInfo,animated?:boolean):void
- pushPathByName(name:string,param:unknown,animated?:boolean):void
- pushPathByName(name:string,param:object,.)
- pushDestination(info:NavPathInfo,animated?:boolean):Promise
interface Param {
name: string,
}
const param5: Param = { name: 'test' };
this.pageInfos.pushpathByname('page5', param5);
pushPathByName的参数分别为页面名称、页面参数以及是否启动动画(默认值为true)
replace系列方法:将当前页面栈栈顶退出,再将指定的NavDestination页面信息入栈。
- replacePath(info:NavPathInfo,animated?:boolean):void
- replacePathByName(name:string,param:0bject,animated?:boolean):void
interface Param {
name: string,
}
const param1:Param={name:'test'};
this.pageInfos.replacePathByName('Page1',param5);
//将原本的page5页面替换为page1页面
1.4 路由传参和路由参数的获取
getParamByIndex(index:number):unknown | undefined获取index指定的NavDestination页面的参数信息
this.pageInfos.getParamByIndex(0) as Param;// param1
this.pageInfos.getParamByIndex(1) as Param;// param2
getParamByName(name: string): Array获取全部名为name的NavDestination页面的参数信息。
this.pageInfos.getParamByName('Page1')as Param[]; // [param1, param5] 因为之前将page5换为page1,所带参数为param5
this.pageInfos.getParamByName('Page2')as Param[];// [param2]
2. Tabs组件
2.1 基础概念
当页面信息较多时,为了让用户能够聚焦于当前显示的内容,需要对页面内容进行分类,提高页面空间利用率。Tabs组件可以在一个页面内快速实现视图内容的切换,一方面提升查找信息的效率,另一方面精简用户单次获取到的信息量。
Tabs(value?:fbarPosition?:BarPosition, index?: number,controller?:Tabscontroller})
-
barPosition:设置Tabs的页签位置。
-
index:设置当前显示页签的索引。
-
controller:设置Tabs控制器。
TabBar按照不同的导航栏类型可以分为底部导航 、顶部导航、侧边导航。其导航栏分别位于底部顶部和侧边。
2.2 组件的使用
- controller
tabs参数所传入的TabsController实例可以对Tabs显示的TabContent区域进行控制,控制方式是使用实例的changeindex方法,该方法需要传入一个数值,能控制Tabs显示到对应的索引。
- 关联contreller与Tabs
struct Index {
private tabsController: TabsController = new TabsController();
Tabs({ controller: tabsController }) {// 关联controller与Tabs
...
}
}
- 控制Tabs的TabContent区域显示的内容
this.tabsController.changeIndex(1)
- 自定义TabBar
对于底部导航栏,一般作为应用主页面功能区分,为了更好的用户体验,会组合文字以及对应语义图标表示页签内容,这种情况下,需要自定义导航页签的样式
@Builder
tabBarBuilder(title: string,
targetIndex:number,
selectedIcon:Resource
unselectIcon:Resource
) {
Column(){
Image(this.currentIndex=== targetIndex ?selectedIcon : unselectIcon)
.width(24)
.height(24)
Text(title)
.fontFamily('HarmonyHeiTi-Medium')
.fontsize(10)
.fontColor(this.currentIndex=== targetIndex ?'#0A59F7':'#9908000g')
.textAlign(TextAlign.center)
.lineHeight(14)
.fontWeight(500)
}
}
3. 使用Tabs设置组件导航
- 使用Tabs组件
@Entry
@Component
struct Index {
@State message: string = 'Hello World';
build() {
Tabs({ barPosition: BarPosition.End}){ //设置导航页签栏位于应用界面的底部
TabContent() {
Text('Tabcontent1')
}
.tabBar('TabBar1')
//每一个TabContent对应的内容需要有一个页签,可以通过TabContent的tabBar属性进行配置。
TabContent() {
Text('Tabcontent2')
}
.tabBar('TabBar2')
TabContent() {
Text('Tabcontent3')
}
.tabBar('TabBar3')
TabContent() {
Text('Tabcontent4')
}
.tabBar('TabBar4')
}
.scrollable(false)
.vertical(false)
.divider({
strokeWidth: 0.5,
color: '#0D182431'
})
.backgroundColor('#F1F3F5')
.padding({ top: 36, bottom: 28 })
}
}
- 自定义导航页签栏
由于一般情况下TabBar除了文字还有图标,这种情况下使用默认的tabBar就不适用了,需要开发者自行定义tabBar,建议使用自定义构建函数的方式进行定义。根据设计图,自定义tabBar需要的参数包括了页签的名称,当前页签的索引,选中的图标,未选中的图标。
...
struct Index {
@Builder
tabBarBuilder(title: string, targetIndex: number, selectedIcon: Resource, unselectIcon: Resource) {
}
build() {
...
}
}
- 实现自定义导航页签栏
图标和页签名称呈上下排列,我们可以使用Column组件作为外层容器,内部从上至下依次为图标与页签名称,分别采用Image组件与Text组件进行实现,对于图标,如果当前索引与该页签的索引一致,就采用选中的图标,否则就采用未选中的图标,对于页签名同理,如果当前索引与页签索引一致使用高亮的颜色,否则使用默认颜色,同时我们定义当前的页签索引状态变量currentIndex,该变量默认为0。
@Entry
@Component
struct Index {
@State currentIndex: number = 0;
@Builder
tabBarBuilder(title: string, targetIndex: number, selectedIcon: Resource, unselectIcon: Resource) {
Column() {
Image(this.currentIndex === targetIndex ? selectedIcon : unselectIcon)
.width(24)
.height(24)
Text(title)
.fontFamily('HarmonyHeiTi-Medium')
.fontSize(10)
.fontColor(this.currentIndex === targetIndex ? '#0A59F7' : 'rgba(0,0,0,0.60)')
.textAlign(TextAlign.Center)
.lineHeight(14)
.fontWeight(500)
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Center)
}
build() {
...
}
}
- 使用自定义的tabBar
修改之前写的TabContent的tabBar属性的参数,采用刚才定义的tabBarBuilder自定义构建函数,传入对应的参数
build() {
Tabs({ barPosition: BarPosition.End}){ //设置导航页签栏位于应用界面的底部
TabContent() {
Text('快速入门页面')
}
.tabBar(this.tabBarBuilder('快速入门', 0, $r('app.media.ic_01_on'), $r('app.media.ic_01_off')))
TabContent() {
Text('课程学习页面')
}
.tabBar(this.tabBarBuilder('课程学习', 1, $r('app.media.ic_01_on'), $r('app.media.ic_01_off')))
TabContent() {
Text('知识地图页面')
}
.tabBar(this.tabBarBuilder('知识地图', 2, $r('app.media.ic_01_on'), $r('app.media.ic_01_off')))
}
.scrollable(false)
.vertical(false)
.divider({
strokeWidth: 0.5,
color: '#0D182431'
})
.backgroundColor('#F1F3F5')
.padding({ top: 36, bottom: 28 })
}
此时已经可以点击切换TabContent的内容区了,但是底部TabBar的导航条高亮无法跟随显示。接下来需要自行实现TabContent的切换及高亮当前页签栏。
5. TabsController
TabsController是Tabs组件的控制器,用于控制Tabs组件进行页签切换。我们后续可以通过TabsController的changeIndex方法来实现跳转至指定索引值对应的TabContent内容。
private tabsController : TabsController = new TabsController();
关联Tabs控制器与Tabs组件。开发者可以将定义的Tabs控制器作为Tabs组件的参数传入,这样就能通过该控制器来对Tabs进行控制
...
struct Index {
...
build() {
Tabs({ barPosition: BarPosition.End, controller: this.tabsController }) {
...
}
...
}
}
实现点击切换TabContent及高亮显示当前页签栏。可以在自定义构建函数的点击回调中通过改变之前定义的currentIndex状态变量为点击的页签的索引来实现高亮当前页签栏,同时可以通过tabController的changeIndex方法来改变TabContent显示的内容。
...
struct Index {
...
@Builder
tabBarBuilder(title: string, targetIndex: number, selectedIcon: Resource, unselectIcon: Resource) {
Column() {
...
}
...
.onClick(() => {
this.currentIndex = targetIndex;
this.tabsController.changeIndex(targetIndex);
})
}
build() {
...
}
}