写点什么

OpenHarmony 应用开发之 Navigation 组件详解

作者:坚果
  • 2022 年 7 月 05 日
  • 本文字数:9713 字

    阅读完需:约 32 分钟

页面导航(Navigation)

Navigation 一般作为 Page 页面的根容器,通过属性设置来展示页面的标题、它提供了一系列属性方法来设置页面的标题栏、工具栏以及菜单栏的各种展示样式。 Navigation 除了提供了默认的展示样式属性外,它还提供了 CustomBuilder 模式来自定义展示样式,本节将介绍一下 Navigation 各属性的简单用法以及使用 CustomBuilder 实现自定义样式。

Navigation 定义介绍

interface NavigationInterface {  /**   * Called when the navigator view interface is used.       */  (): NavigationAttribute;}
复制代码


Navigation 的定义不需要传递相关参数,我们先看下 Navigation 的最简单样例:


@Entry@Componentstruct 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@Componentstruct 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@Componentstruct 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())    }  }
复制代码


样例运行结果如下图所示:



hideTitleBarhideToolBar:设置是否显示或者隐藏标题栏、工具栏,简单样例如下所示:


@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 枚举说明


Navigation 事件介绍

declare class NavigationAttribute extends CommonMethod<NavigationAttribute> {  onTitleModeChange(callback: (titleMode: NavigationTitleMode) => void): NavigationAttribute;}
复制代码


  • onTitleModeChange:当 titleModeNavigationTitleMode.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 界面了。

参考

  • [Navigation](ying y

发布于: 刚刚阅读数: 3
用户头像

坚果

关注

此间若无火炬,我便是唯一的光 2020.10.25 加入

公众号:“大前端之旅”,华为云享专家,InfoQ签约作者,51CTO博客首席体验官,专注于大前端技术的分享,包括Flutter,小程序,安卓,VUE,JavaScript。

评论

发布
暂无评论
OpenHarmony应用开发之Navigation组件详解_HarmonyOS_坚果_InfoQ写作社区