#夏日挑战赛#OpenHarmony应用开发之页面导航(Navigation)组件 原创 精华
页面导航(Navigation)详解
Navigation
一般作为Page页面的根容器,通过属性设置来展示页面的标题、它提供了一系列属性方法来设置页面的标题栏、工具栏以及菜单栏的各种展示样式。 Navigation
除了提供了默认的展示样式属性外,它还提供了 CustomBuilder
模式来自定义展示样式,本节将介绍一下 Navigation
各属性的简单用法以及使用 CustomBuilder
实现自定义样式。
Navigation定义介绍
interface NavigationInterface {
/**
* Called when the navigator view interface is used.
*/
(): NavigationAttribute;
}
Navigation
的定义不需要传递相关参数,我们先看下 Navigation
的最简单样例:
@Entry
@Component
struct ResourceTest {
@State text_string: string = "跟着坚果学习OpenHarmony应用开发";
build() {
Navigation() { // Navigation只能包含一个子组件
}
}
}
运行结果如下图所示:
由运行结果可知,在默认情况下, Navigation
的样式是一个带有返回箭头的标题栏组成的。
Navigation属性介绍
我们可以点开它的方法看一下,首先他也是继承了CommonMethod,然后对其进行自定义。
declare class NavigationAttribute extends CommonMethod<NavigationAttribute> {
/**
* 设置导航栏的标题,当参数类型为 `string` 时,可以直接设置标题,当参数为 `CustomBuilder` 时,可以自定义标题样式。
*/
title(value: string | CustomBuilder): NavigationAttribute;
/**
* Navigation subtitle
*/
subTitle(value: string): NavigationAttribute;
/**
* Hide navigation bar
*/
hideTitleBar(value: boolean): NavigationAttribute;
/**
* Hide navigation back button
*/
hideBackButton(value: boolean): NavigationAttribute;
/**
* Navigation title mode
*/
titleMode(value: NavigationTitleMode): NavigationAttribute;
/**
* Navigation title bar's menus
*/
menus(value: Array<NavigationMenuItem> | CustomBuilder): NavigationAttribute;
/**
* Tool bar
*/
toolBar(value: object | CustomBuilder): NavigationAttribute;
/**
* Hide tool bar
*/
hideToolBar(value: boolean): NavigationAttribute;
/**
* Trigger callback when title mode change finished at free mode.
*/
onTitleModeChange(callback: (titleMode: NavigationTitleMode) => void): NavigationAttribute;
}
title:设置导航栏的标题,当参数类型为 string
时,可以直接设置标题,但样式不支修改;当参数为 CustomBuilder
时,可以自定义标题样式。
-
参数类型为
string
,简单样例如下所示:@Entry @Component struct ResourceTest { @State content: string = "跟着坚果学习OpenHarmony应用开发"; @State title: string = "这是标题"; build() { Navigation() { Text(this.content) .textAlign(TextAlign.Center) .fontSize(30) .backgroundColor(Color.Orange) .size({ width: '100%', height: '100%' }) } .size({ width: '100%', height: '100%' }) .title(this.title) // 设置title,此时不支持修改文字大小,颜色等样式 } }
样例运行结果如下图所示:
-
参数类型为
CustomBuilder
,简单样例如下所示:@Entry @Component struct ResourceTest { @State content: string = "跟着坚果学习OpenHarmony应用开发"; @State title: string = "这是标题"; @Builder titleWidget() {// 通过Builder自定义标题栏,可以灵活的设置标题样式 Row() { Text(this.title).textAlign(TextAlign.Center) .fontSize(20).margin({right:20}) Image($r("app.media.door_lock")).width(30) }.justifyContent(FlexAlign.Center) .width('100%') .height(30) .backgroundColor(Color.Gray) } build() { Navigation() { Text(this.content) .textAlign(TextAlign.Center) .fontSize(30) .backgroundColor(Color.Orange) .size({ width: '100%', height: '100%' }) } .size({ width: '100%', height: '100%' }) .title(this.titleWidget) // 设置title,此时不支持修改文字大小,颜色等样式 } }
样例运行结果如下图所示(为了观察的更细致,我只截了上半部分):
subTitle:设置页面的副标题,简单样例如下所示:
@Entry
@Component
struct ResourceTest {
@State content: string = "跟着坚果学习OpenHarmony应用开发";
@State title: string = "这是标题";
@State sub_title: string = "这是副标题";
@Builder titleWidget() {// 通过Builder自定义标题栏,可以灵活的设置标题样式
Row() {
Text(this.title).textAlign(TextAlign.Center)
.fontSize(20).margin({right:20})
Image($r("app.media.door_lock")).width(30)
}.justifyContent(FlexAlign.Center)
.width('100%')
.height(30)
.backgroundColor(Color.Gray)
}
build() {
Navigation() {
Text(this.content)
.textAlign(TextAlign.Center)
.fontSize(30)
.backgroundColor(Color.Orange)
.size({ width: '100%', height: '100%' })
}
.size({ width: '100%', height: '100%' })
.title(this.titleWidget) // 设置title,此时不支持修改文字大小,颜色等样式
.subTitle(this.sub_title)
}
}
样例运行结果如下图所示:
hideBackButton:是否隐藏返回按钮,默认情况下不隐藏,简单样例如下所示:
@Entry
@Component
struct ResourceTest {
@State content: string = "跟着坚果学习OpenHarmony应用开发";
@State title: string = "这是标题";
@State sub_title: string = "这是副标题";
@Builder titleWidget() {// 通过Builder自定义标题栏,可以灵活的设置标题样式
Row() {
Text(this.title).textAlign(TextAlign.Center)
.fontSize(20).margin({right:20})
Image($r("app.media.door_lock")).width(30)
}.justifyContent(FlexAlign.Center)
.width('100%')
.height(30)
.backgroundColor(Color.Gray)
}
build() {
Navigation() {
Text(this.content)
.textAlign(TextAlign.Center)
.fontSize(30)
.backgroundColor(Color.Orange)
.size({ width: '100%', height: '100%' })
}
.size({ width: '100%', height: '100%' })
.title(this.titleWidget) // 设置title,此时不支持修改文字大小,颜色等样式
.subTitle(this.sub_title)// 设置subTitle,此时不支持修改文字大小,颜色等样式
.hideBackButton(true)
}
}
样例运行结果如下图所示:
toolBar:设置工具栏,当参数类型为 object
时,可以直接设置工具栏选项,但样式不支修改;当参数为 CustomBuilder
时,可以自定义标题栏。
-
当参数为
object
类型时,参数需要按照如下格式定义:- value:工具栏单个选项的显示文本。
- icon:工具栏单个选项的图标资源路径。
- action:当前选项被选中时的事件回调。
简单样例如下所示:
@Entry @Component struct ResourceTest { @State content: string = "跟着坚果学习OpenHarmony应用开发"; @State title: string = "这是标题"; @State sub_title: string = "这是副标题"; @Builder titleWidget() { // 通过Builder自定义标题栏,可以灵活的设置标题样式 Row() { Text(this.title).textAlign(TextAlign.Center) .fontSize(20).margin({ right: 20 }) Image($r("app.media.door_lock")).width(30) }.justifyContent(FlexAlign.Center) .width('100%') .height(30) .backgroundColor(Color.Gray) } build() { Navigation() { Text(this.content) .textAlign(TextAlign.Center) .fontSize(30) .backgroundColor(Color.Orange) .size({ width: '100%', height: '100%' }) } .size({ width: '100%', height: '100%' }) .title(this.titleWidget) // 设置title,此时不支持修改文字大小,颜色等样式 .subTitle(this.sub_title) // 设置subTitle,此时不支持修改文字大小,颜色等样式 .hideBackButton(true) .toolBar({ items: [ // toolBar接收一个数组 { value: "消息", // 文本 action: () => { // 事件 console.log("点击了消息") } }, { value: "动态", action: () => { console.log("点击了首页") } }, { value: "我的", action: () => { console.log("点击了首页") } } ] }) } }
样例运行结果如下图所示:
-
当参数为
CustomBuilder
类型时,可以自定义样式,简单样例如下所示:@Entry @Component struct ComponentTest { @State index: number = 0;// 选项卡下标,默认为第一个 @Builder toolbarWidget() {// 通过builder自定义toolbar Row() { Column() { Image(this.index == 0 ? 'common/images/tab-home-Select.png' : 'common/images/tab-home-Unchecked.png') .size({width: 25, height: 25}).margin({bottom:4,top:4}) Text('主页') .fontSize(16) .fontColor(this.index == 0 ? Color.Orange : null) } .alignItems(HorizontalAlign.Center) .height('100%') .layoutWeight(1) .onClick(() => { this.index = 0; }) Column() { Image(this.index == 1 ? 'common/images/tab-my-Select.png' : 'common/images/tab-my-Unchecked.png') .size({width: 25, height: 25}).margin({bottom:4,top:4}) Text('汪汪') .fontSize(16) .fontColor(this.index == 1 ? Color.Orange : null) } .alignItems(HorizontalAlign.Center) .height('100%') .layoutWeight(1) .onClick(() => { this.index = 1; }) Column() { Image(this.index == 2 ? 'common/images/tab-news-Select.png' : 'common/images/tab-news-Unchecked.png') .size({width: 25, height: 25}).margin({bottom:4,top:4}) Text('消息') .fontSize(16) .fontColor(this.index == 2 ? Color.Orange : null) } .alignItems(HorizontalAlign.Center) .height('100%') .layoutWeight(1) .onClick(() => { this.index = 2; }) } .width('100%') .height(60) } build() { Navigation() { Text(this.index == 0 ? "主页" : this.index == 1 ? "汪汪" : "消息") .textAlign(TextAlign.Center) .fontSize(30) .size({width: '100%', height: '100%'}) .backgroundColor(Color.Orange) } .size({width: '100%', height: '100%'}) .title("跟着坚果学OpenHarmony") .toolBar(this.toolbarWidget()) } }
样例运行结果如下图所示:
hideTitleBar、hideToolBar:设置是否显示或者隐藏标题栏、工具栏,简单样例如下所示:
@Entry @Component struct ComponentTest {
@State index: number = 0;// 选项卡下标,默认为第一个
@State hideToolBar: boolean = false;
@State hideTitleBar: boolean = false;
@Builder toolbarWidget() {// 通过builder自定义toolbar
Row() {
Column() {
Image(this.index == 0 ? 'common/images/tab-home-Select.png' : 'common/images/tab-home-Unchecked.png')
.size({width: 25, height: 25}).margin({bottom:4,top:4})
Text('主页')
.fontSize(16)
.fontColor(this.index == 0 ? Color.Orange : null)
}
.alignItems(HorizontalAlign.Center)
.height('100%')
.layoutWeight(1)
.onClick(() => {
this.index = 0;
})
Column() {
Image(this.index == 1 ? 'common/images/tab-my-Select.png' : 'common/images/tab-my-Unchecked.png')
.size({width: 25, height: 25}).margin({bottom:4,top:4})
Text('汪汪')
.fontSize(16)
.fontColor(this.index == 1 ? Color.Orange : null)
}
.alignItems(HorizontalAlign.Center)
.height('100%')
.layoutWeight(1)
.onClick(() => {
this.index = 1;
})
Column() {
Image(this.index == 2 ? 'common/images/tab-news-Select.png' : 'common/images/tab-news-Unchecked.png')
.size({width: 25, height: 25}).margin({bottom:4,top:4})
Text('消息')
.fontSize(16)
.fontColor(this.index == 2 ? Color.Orange : null)
}
.alignItems(HorizontalAlign.Center)
.height('100%')
.layoutWeight(1)
.onClick(() => {
this.index = 2;
})
}
.width('100%')
.height(60)
}
build() {
Navigation() {
Column({space: 20}) {
Text(this.index == 0 ? "主页" : this.index == 1 ? "汪汪" : "消息")
.textAlign(TextAlign.Center)
.fontSize(30)
Button(this.hideTitleBar ? "显示TitleBar" : "隐藏TitleBar")
.onClick(() => {
this.hideTitleBar = !this.hideTitleBar;
}).backgroundColor(Color.Green)
Button(this.hideToolBar ? "显示ToolBar" : "隐藏ToolBar")
.onClick(() => {
this.hideToolBar = !this.hideToolBar;
}).backgroundColor(Color.Red)
}
.backgroundColor(Color.Orange).justifyContent(FlexAlign.SpaceAround).alignItems(HorizontalAlign.Center).justifyContent(FlexAlign.Center)
.size({width: '100%', height: '100%'})
}
.size({width: '100%', height: '100%'})
.title("跟着坚果学OpenHarmony")
.toolBar(this.toolbarWidget()) .hideToolBar(this.hideToolBar)
.hideTitleBar(this.hideTitleBar)
}
}
样例运行结果如下图所示:
menus:设置标题栏右上角的菜单项,当参数为 CustomBuilder
时可以自定义菜单项。
-
当参数为
NavigationMenuItem
数组时,参数说明如下:- value:菜单项的显示文本。
- icon:菜单项的显示图标路径。
- action:点击菜单项的事件回调。
简单样例如下所示:
@Entry @Component struct ComponentTest { @State index: number = 0;// 选项卡下标,默认为第一个 @State hideToolBar: boolean = false; @State hideTitleBar: boolean = false; @Builder toolbarWidget() {// 通过builder自定义toolbar Row() { Column() { Image(this.index == 0 ? 'common/images/tab-home-Select.png' : 'common/images/tab-home-Unchecked.png') .size({width: 25, height: 25}).margin({bottom:4,top:4}) Text('主页') .fontSize(16) .fontColor(this.index == 0 ? Color.Orange : null) } .alignItems(HorizontalAlign.Center) .height('100%') .layoutWeight(1) .onClick(() => { this.index = 0; }) Column() { Image(this.index == 1 ? 'common/images/tab-my-Select.png' : 'common/images/tab-my-Unchecked.png') .size({width: 25, height: 25}).margin({bottom:4,top:4}) Text('汪汪') .fontSize(16) .fontColor(this.index == 1 ? Color.Orange : null) } .alignItems(HorizontalAlign.Center) .height('100%') .layoutWeight(1) .onClick(() => { this.index = 1; }) Column() { Image(this.index == 2 ? 'common/images/tab-news-Select.png' : 'common/images/tab-news-Unchecked.png') .size({width: 25, height: 25}).margin({bottom:4,top:4}) Text('消息') .fontSize(16) .fontColor(this.index == 2 ? Color.Orange : null) } .alignItems(HorizontalAlign.Center) .height('100%') .layoutWeight(1) .onClick(() => { this.index = 2; }) } .width('100%') .height(60) } build() { Navigation() { Column({space: 20}) { Text(this.index == 0 ? "主页" : this.index == 1 ? "汪汪" : "消息") .textAlign(TextAlign.Center) .fontSize(30) Button(this.hideTitleBar ? "显示TitleBar" : "隐藏TitleBar") .onClick(() => { this.hideTitleBar = !this.hideTitleBar; }).backgroundColor(Color.Green) Button(this.hideToolBar ? "显示ToolBar" : "隐藏ToolBar") .onClick(() => { this.hideToolBar = !this.hideToolBar; }).backgroundColor(Color.Red) } .backgroundColor(Color.Orange).justifyContent(FlexAlign.SpaceAround).alignItems(HorizontalAlign.Center).justifyContent(FlexAlign.Center) .size({width: '100%', height: '100%'}) } .size({width: '100%', height: '100%'}) .title("跟着坚果学OpenHarmony") .toolBar(this.toolbarWidget()) .hideToolBar(this.hideToolBar) .hideTitleBar(this.hideTitleBar) .menus([ { value: "关门", icon: 'common/images/door_lock.svg', action: () => { } }, { value: "开们", icon: 'common/images/door_unlock.svg', action: () => { } } ]) } }
样例运行结果如下图所示:
titleMode: 页面标题栏显示模式,默认为NavigationTitleMode.Free
NavigationTitleMode枚举说明
名称 描述 Free 当内容为可滚动组件时,标题随着内容向上滚动而缩小(子标题的大小不变、淡出)。向下滚动内容到顶时则恢复原样。 Mini 固定为小标题模式(图标+主副标题)。 Full 固定为大标题模式(主副标题)。
Navigation事件介绍
declare class NavigationAttribute extends CommonMethod<NavigationAttribute> {
onTitleModeChange(callback: (titleMode: NavigationTitleMode) => void): NavigationAttribute;
}
- onTitleModeChange:当
titleMode
为 NavigationTitleMode.Free 时,随着可滚动组件的滑动标题栏模式发生变化时触发此回调。
@Entry @Component struct ComponentTest {
@State index: number = 0;// 选项卡下标,默认为第一个
@State hideToolBar: boolean = false;
@State hideTitleBar: boolean = false;
@Builder toolbarWidget() {// 通过builder自定义toolbar
Row() {
Column() {
Image(this.index == 0 ? 'common/images/tab-home-Select.png' : 'common/images/tab-home-Unchecked.png')
.size({width: 25, height: 25}).margin({bottom:4,top:4})
Text('主页')
.fontSize(16)
.fontColor(this.index == 0 ? Color.Orange : null)
}
.alignItems(HorizontalAlign.Center)
.height('100%')
.layoutWeight(1)
.onClick(() => {
this.index = 0;
})
Column() {
Image(this.index == 1 ? 'common/images/tab-my-Select.png' : 'common/images/tab-my-Unchecked.png')
.size({width: 25, height: 25}).margin({bottom:4,top:4})
Text('汪汪')
.fontSize(16)
.fontColor(this.index == 1 ? Color.Orange : null)
}
.alignItems(HorizontalAlign.Center)
.height('100%')
.layoutWeight(1)
.onClick(() => {
this.index = 1;
})
Column() {
Image(this.index == 2 ? 'common/images/tab-news-Select.png' : 'common/images/tab-news-Unchecked.png')
.size({width: 25, height: 25}).margin({bottom:4,top:4})
Text('消息')
.fontSize(16)
.fontColor(this.index == 2 ? Color.Orange : null)
}
.alignItems(HorizontalAlign.Center)
.height('100%')
.layoutWeight(1)
.onClick(() => {
this.index = 2;
})
}
.width('100%')
.height(60)
}
build() {
Navigation() {
Column({space: 20}) {
Text(this.index == 0 ? "主页" : this.index == 1 ? "汪汪" : "消息")
.textAlign(TextAlign.Center)
.fontSize(30)
Button(this.hideTitleBar ? "显示TitleBar" : "隐藏TitleBar")
.onClick(() => {
this.hideTitleBar = !this.hideTitleBar;
}).backgroundColor(Color.Green)
Button(this.hideToolBar ? "显示ToolBar" : "隐藏ToolBar")
.onClick(() => {
this.hideToolBar = !this.hideToolBar;
}).backgroundColor(Color.Red)
}
.backgroundColor(Color.Orange).justifyContent(FlexAlign.SpaceAround).alignItems(HorizontalAlign.Center).justifyContent(FlexAlign.Center)
.size({width: '100%', height: '100%'})
}
.size({width: '100%', height: '100%'})
.title("跟着坚果学OpenHarmony")
.toolBar(this.toolbarWidget()) .hideToolBar(this.hideToolBar)
.hideTitleBar(this.hideTitleBar) .menus([
{
value: "关门",
icon: 'common/images/door_lock.svg',
action: () => {
}
},
{
value: "开们",
icon: 'common/images/door_unlock.svg',
action: () => {
}
}
]).onTitleModeChange((titleModel: NavigationTitleMode) => {
console.log('titleMode')
}) .titleMode(NavigationTitleMode.Free)
}
}
效果
小结
大家了解完这个组件,是不是对UI开发,有了更加直观的认识,在我看来,只要大家学会了这个组件的使用,那么我相信,大部分的UI都可以实现了。
了 Navigation
组件的基本使用,读者掌握了该组件的使用后可以开发更丰富的 UI 界面了。
这个组件不错哎,使用好了,可以节省代码量
很不错,学习了,绝世好文,前排留名