1.Navigation
类似IOS和Android,Harmony的Navigation也是功能丰富的页面根容器,在构建应用程序的用户界面时发挥着核心作用。它不仅提供了灵活的显示模式选择,如单页面、分栏以及自适应模式,还允许开发者精细定制标题栏、工具栏、导航栏等关键元素,以满足不同应用场景的需求。本文将详细介绍Navigation组件的构成、各显示模式的设定方法以及如何配置其相关属性。
Navigation 组件构成与子组件
主页与内容页
Navigation 组件的页面结构由主页和内容页两部分组成。主页通常包括标题栏、内容区和工具栏。标题栏展示页面名称,工具栏则承载辅助功能按钮。在内容区中,开发者可以嵌入NavRouter
子组件,以此实现导航栏功能。NavRouter
负责处理用户点击事件,简化了开发过程,无需开发者自定义复杂的点击事件逻辑。
NavRouter 与 NavDestination
NavRouter
是与Navigation紧密协作的特殊子组件,其设计目的是简化页面间的导航操作。NavRouter
具有两个子组件,其中第二个子组件必须为NavDestination
。NavDestination
则用于承载Navigation内容页的具体内容。当用户点击NavRouter
时,系统自动跳转至相应的NavDestination
内容区,实现了平滑的页面过渡。
设置页面显示模式
自适应模式(默认)
Navigation 组件默认采用自适应模式,此时mode
属性设为NavigationMode.Auto
。在自适应模式下,组件会依据设备宽度动态调整布局。当设备宽度超过520vp时,组件切换为分栏模式;反之,则采用单页面模式。
Navigation()
.mode(NavigationMode.Auto)
单页面模式
通过将mode
属性设置为NavigationMode.Stack
,可将Navigation组件设定为单页面显示模式。这种模式适用于需要聚焦单一内容区域、避免屏幕空间分割的应用场景。
Navigation()
.mode(NavigationMode.Stack)
分栏模式
将mode
属性设为NavigationMode.Split
,Navigation组件即进入分栏模式。此模式下,页面被划分为多个并列区域,便于同时展示和操作多个内容模块。
@Entry
@Component
struct NavigationExample {
private arr: number[] = [1, 2, 3];
build() {
Column() {
Navigation() {
TextInput({ placeholder: 'search...' })
.width("90%")
.height(40)
.backgroundColor('#FFFFFF')
List({ space: 12 }) {
ForEach(this.arr, (item) => {
ListItem() {
NavRouter() {
Text("NavRouter" + item)
.width("100%")
.height(72)
.backgroundColor('#FFFFFF')
.borderRadius(24)
.fontSize(16)
.fontWeight(500)
.textAlign(TextAlign.Center)
NavDestination() {
Text("NavDestinationContent" + item)
}
.title("NavDestinationTitle" + item)
}
}
}, item => item)
}
.width("90%")
.margin({ top: 12 })
}
.title("主标题")
.mode(NavigationMode.Split)
.menus([
{value: "", icon: "./image/ic_public_search.svg", action: ()=> {}},
{value: "", icon: "./image/ic_public_add.svg", action: ()=> {}},
{value: "", icon: "./image/ic_public_add.svg", action: ()=> {}},
{value: "", icon: "./image/ic_public_add.svg", action: ()=> {}},
{value: "", icon: "./image/ic_public_add.svg", action: ()=> {}}
])
.toolBar({items: [
{value: "func", icon: "./image/ic_public_highlights.svg", action: ()=> {}},
{value: "func", icon: "./image/ic_public_highlights.svg", action: ()=> {}},
{value: "func", icon: "./image/ic_public_highlights.svg", action: ()=> {}}
]})
}
.height('100%')
.width('100%')
.backgroundColor('#F1F3F5')
}
}
定制标题栏、菜单栏与工具栏
标题栏模式
标题栏位于界面顶部,用于展示界面名称及操作入口。通过titleMode
属性,开发者可选择标题栏的呈现风格:
- Mini模式:适用于一级页面,当标题无需突出显示时,采用简洁的迷你标题栏设计。
Navigation()
.titleMode(NavigationTitleMode.Mini)
- Full模式:对于需要强调标题的一级页面,选择全尺寸标题栏,以增强视觉焦点。
Navigation()
.titleMode(NavigationTitleMode.Full)
菜单栏
菜单栏位于Navigation组件右上角,可通过menus
属性进行配置。支持传入Array<NavigationMenuItem>
或自定义构建器CustomBuilder
。数组形式的配置最多可显示一定数量的图标(竖屏3个,横屏5个),超出部分将自动归入“更多”图标中。
// 示例:设置3个菜单图标
Navigation()
.menus([
{ value: "", icon: "./image/ic_public_search.svg", action: () => {} },
{ value: "", icon: "./image/ic_public_add.svg", action: () => {} },
{ value: "", icon: "./image/ic_public_add.svg", action: () => {} },
])
工具栏
工具栏位于Navigation组件底部,通过toolBar
属性进行设置,包含一系列操作项。每个项包含值、图标及对应的操作回调函数。
Navigation()
.toolBar({
items: [
{ value: "func", icon: "./image/ic_public_highlights.svg", action: () => {} },
{ value: "func", icon: "./image/ic_public_highlights.svg", action: () => {} },
{ value: "func", icon: "./image/ic_public_highlights.svg", action: () => {} },
],
})
2.Tabs
当应用程序需要展示大量信息且期望用户能够清晰聚焦于当前内容时,对页面内容进行有效分类与布局至关重要。Tabs 组件便是在一个页面内实现视图内容快速切换的理想工具,它不仅能提升信息查找效率,还能减少用户单次接收的信息量,从而优化用户体验。以下将详述 Tabs 组件的基本布局、不同导航类型及其配置方法,以及如何实现自定义导航栏、内容与页签联动等高级功能。
基本布局与配置
Tabs 组件结构
Tabs 组件主要由两部分构成:TabContent(内容页)和 TabBar(导航页签栏)。TabContent 不支持设置通用宽度与高度属性,其宽度自动撑满 Tabs 父组件,高度由 Tabs 父组件高度与 TabBar 高度共同决定。通过在 Tabs 中按顺序放置多个 TabContent,即可实现内容的分类展示。
Tabs() {
TabContent() {
Text('首页的内容').fontSize(30)
}
.tabBar('首页')
TabContent() {
Text('推荐的内容').fontSize(30)
}
.tabBar('推荐')
TabContent() {
Text('发现的内容').fontSize(30)
}
.tabBar('发现')
TabContent() {
Text('我的内容').fontSize(30)
}
.tabBar("我的")
}
导航类型与布局
底部导航
底部导航是应用中最常见的导航形式,位于一级页面底部,便于用户识别功能分类、快速切换内容,且适合单手操作。通过设置 barPosition
参数为 BarPosition.End
实现底部导航:
Tabs({ barPosition: BarPosition.End }) {
// TabContent 的内容:首页、发现、推荐、我的
...
}
顶部导航
当内容分类较多,需要频繁切换时,可采用顶部导航模式。顶部导航作为对底部导航的补充或替代,常用于资讯类应用。Tabs 组件默认 barPosition
为 BarPosition.Start
,即为顶部导航模式:
Tabs({ barPosition: BarPosition.Start }) {
// TabContent 的内容:关注、视频、游戏、数码、科技、体育、影视
...
}
侧边导航
侧边导航适用于平板横屏界面,导航栏默认位于左侧。启用侧边导航需设置 vertical
为 true
,并调整 barWidth
和 barHeight
为合适的值:
Tabs({ barPosition: BarPosition.Start }) {
// TabContent 的内容:首页、发现、推荐、我的
...
}
.vertical(true)
.barWidth(100)
.barHeight(200)
导航栏行为控制
限制滑动切换
为避免与其他导航元素冲突,可通过设置 scrollable
属性为 false
来禁止导航栏滑动切换:
Tabs({ barPosition: BarPosition.End }) {
TabContent(){
Column(){
// 顶部导航栏内容
...
}
.backgroundColor('#ff08a8f1')
.width('100%')
}
.tabBar('首页')
// 其他 TabContent 内容:发现、推荐、我的
...
}
.scrollable(false)
固定与滚动导航栏
- 固定导航栏(
barMode: BarMode.Fixed
):适用于分类固定且数量较少的情况,页签均匀分布且不可滚动。
Tabs({ barPosition: BarPosition.End }) {
// TabContent 的内容:首页、发现、推荐、我的
...
}
.barMode(BarMode.Fixed)
- 滚动导航栏(
barMode: BarMode.Scrollable
):当内容分类较多,屏幕无法容纳所有页签时,使用可滚动导航栏。
Tabs({ barPosition: BarPosition.Start }) {
// TabContent 的内容:关注、视频、游戏、数码、科技、体育、影视、人文、艺术、自然、军事
...
}
.barMode(BarMode.Scrollable)
自定义导航栏
样式定制
通过在 tabBar
属性中传入自定义函数组件,可以实现样式上的完全自定义。例如,创建一个 TabBuilder
函数组件,接收页签文字、目标索引、选中与未选中状态的图片资源作为参数,根据当前活跃索引和目标索引匹配情况决定显示样式:
@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)
}
// 在 TabContent 对应 tabBar 属性中传入自定义函数组件
TabContent() {
...
}
.tabBar(this.TabBuilder('我的', 0, $r('app.media.mine_selected'), $r('app.media.mine_normal')))
切换逻辑
使用自定义导航栏时,需要手动实现页签与内容的切换逻辑。借助 TabsController
控制器,通过其 changeIndex
方法切换至指定索引的 TabContent:
private tabsController : TabsController = new TabsController()
@State currentIndex:number = 0;
@Builder TabBuilder(title: string, targetIndex: number) {
Column() {
Text(title)
.fontColor(this.currentIndex === targetIndex ? '#1698CE' : '#6B6B6B')
}
...
.onClick(() => {
this.currentIndex = targetIndex;
this.tabsController.changeIndex(this.currentIndex);
})
}
// 在 tabBar 属性中传入自定义函数组件
Tabs({ barPosition: BarPosition.End, controller: this.tabsController }) {
TabContent(){
...
}.tabBar(this.TabBuilder('首页',0))
// 其他 TabContent
...
}
滑动联动
使用自定义导航栏时,需监听 onChange
事件以确保滑动页面时,页签栏能同步切换至对应内容页签:
Tabs({ barPosition: BarPosition.End, controller: this.tabsController }) {
// TabContent 定义
...
}.onChange((index) => {
this.currentIndex = index
})
综上所述,Tabs 组件结合各种导航类型、自定义样式与逻辑控制,为应用程序提供了强大的内容分类与切换功能。通过合理配置与运用,可以显著提升用户在复杂信息环境下的浏览效率与体验满意度。