#夏日挑战赛#OpenHarmony应用开发之页面导航(Navigation)组件 原创 精华

鸿蒙坚果派
发布于 2022-7-5 12:32
浏览
1收藏

本文正在参加星光计划3.0–夏日挑战赛

页面导航(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只能包含一个子组件
    }
  }
}

运行结果如下图所示:

#夏日挑战赛#OpenHarmony应用开发之页面导航(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,此时不支持修改文字大小,颜色等样式
      }
    }
    

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

    #夏日挑战赛#OpenHarmony应用开发之页面导航(Navigation)组件-鸿蒙开发者社区

  • 参数类型为 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,此时不支持修改文字大小,颜色等样式
      }
    }
    

    样例运行结果如下图所示(为了观察的更细致,我只截了上半部分):

    #夏日挑战赛#OpenHarmony应用开发之页面导航(Navigation)组件-鸿蒙开发者社区

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)
  }
}

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

#夏日挑战赛#OpenHarmony应用开发之页面导航(Navigation)组件-鸿蒙开发者社区

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)
  }
}

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

#夏日挑战赛#OpenHarmony应用开发之页面导航(Navigation)组件-鸿蒙开发者社区

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("点击了首页")
            }
          }
        ] })
      }
    }
    

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

    #夏日挑战赛#OpenHarmony应用开发之页面导航(Navigation)组件-鸿蒙开发者社区

  • 当参数为 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())
      }
    }
    

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

    #夏日挑战赛#OpenHarmony应用开发之页面导航(Navigation)组件-鸿蒙开发者社区

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)
  }
}

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

#夏日挑战赛#OpenHarmony应用开发之页面导航(Navigation)组件-鸿蒙开发者社区

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: () => {
    
            }
          }
        ])
      }
    }
    

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

    #夏日挑战赛#OpenHarmony应用开发之页面导航(Navigation)组件-鸿蒙开发者社区

    titleMode: 页面标题栏显示模式,默认为NavigationTitleMode.Free

    NavigationTitleMode枚举说明

    名称 描述
    Free 当内容为可滚动组件时,标题随着内容向上滚动而缩小(子标题的大小不变、淡出)。向下滚动内容到顶时则恢复原样。
    Mini 固定为小标题模式(图标+主副标题)。
    Full 固定为大标题模式(主副标题)。

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)
  }
}

效果

#夏日挑战赛#OpenHarmony应用开发之页面导航(Navigation)组件-鸿蒙开发者社区

小结

大家了解完这个组件,是不是对UI开发,有了更加直观的认识,在我看来,只要大家学会了这个组件的使用,那么我相信,大部分的UI都可以实现了。

Navigation 组件的基本使用,读者掌握了该组件的使用后可以开发更丰富的 UI 界面了。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
4
收藏 1
回复
举报
2条回复
按时间正序
/
按时间倒序
程序员小阿杰
程序员小阿杰

这个组件不错哎,使用好了,可以节省代码量

回复
2022-7-5 14:04:55
程序员法医
程序员法医

很不错,学习了,绝世好文,前排留名

回复
2022-7-21 21:15:38
回复
    相关推荐