HarmonyOS NEXT实战:自定义封装多种样式导航栏组件

涉及知识点和装饰器

  • @ComponentV2,@Local, @Builder,@BuilderParam,@Extend, @Require ,@Param,@Event等
  • 第三方库:ZRouter ,如项目中本来就用了ZRouter路由库,案例中点返回按钮直接使用了 ZRouter.pop(),没有用到的话也支持自定义返回事件。

背景:

在项目开发进程中,导航栏的应用场景颇为繁多。以我的页面为例,其导航栏呈现为图标、文字与箭头相组合的样式;而设置页面的导航栏则是图标、文字、右侧文字以及小红点的搭配形式;至于公用顶部导航栏,又表现为左侧返回图标、中间文字、右侧图标与文字的布局。倘若针对每一处用到导航栏的地方均单独编写代码,那么代码的重复编写现象将极为严重。基于此,我们可采用自定义封装的方式构建公用组件。如此一来,不仅为项目后期的维护与拓展提供了极大的便利,同时也能够显著提升开发效率,让开发者有更多精力投入到更具价值的工作思考中,减少不必要的重复劳作时间消耗。

先上效果图

  • 图一
    HarmonyOS NEXT实战:自定义封装多种样式导航栏组件_第1张图片

  • 图二
    HarmonyOS NEXT实战:自定义封装多种样式导航栏组件_第2张图片

  • 图三
    HarmonyOS NEXT实战:自定义封装多种样式导航栏组件_第3张图片

实现 图一 效果图

  • 1、首先需要定义好类型,比如 图片+文字+小红点+返回右键等。
@ObservedV2
export class TabHorizontalModel {
  title: string;
  index: number; //下标
  icon: string | Resource;
  hasIcon: boolean; //是否显示图
  @Trace rightTitle: string;
  hasRightTitle: boolean;
  @Trace hasNew: boolean; //是否显示红点
  hasRightIcon: boolean; //是否显示图

  constructor(title: string, index: number = -1, icon: string | Resource = '', hasIcon: boolean = false, rightTitle: string = '', hasRightTitle: boolean = false, hasNew: boolean = false,
    hasRightIcon: boolean = true) {

    this.icon = icon;
    this.hasIcon = hasIcon;
    this.title = title;
    this.rightTitle = rightTitle;
    this.hasRightTitle = hasRightTitle;
    this.hasNew = hasNew && rightTitle !== '';
    this.index = index;
    this.hasRightIcon = hasRightIcon;
  }
}

  • 2、封装一个通用的 横向Tab 图片、文字、右边文字、小红点 组件
import { CommonConst } from "utils"
import { TabHorizontalModel } from "../model/TabHorizontalModel"

/**
 * Author:J
 * Describe: 横向Tab 图片、文字、右边文字、小红点
 */
@ComponentV2
export struct HorizontalTabItemComp {
  @Param @Require tabItem: TabHorizontalModel= new TabHorizontalModel('')
  @Param onItemClick?: () => void = undefined

  build() {
    Row() {
      Image(this.tabItem.icon)
        .width(24)
        .margin({ right: 12 })
        .visibility(this.tabItem.hasIcon ? Visibility.Visible : Visibility.None)

      Text(this.tabItem.title)
        .fontSize(16)
        .fontColor($r('app.color.color_222222'))
        .layoutWeight(1)
      if (this.tabItem.hasNew) {
        Badge({
          value: '',
          position: BadgePosition.Right,
          style: { badgeSize: 7, badgeColor: $r('app.color.color_FA2A2D') }
        }) {
          Text(this.tabItem.rightTitle)
            .fontSize(16)
            .fontColor($r('app.color.color_222222'))
            .visibility(this.tabItem.hasRightTitle ? Visibility.Visible : Visibility.None)
            .margin({ right: 20 })
        }
      } else {
        Text(this.tabItem.rightTitle)
          .fontSize(16)
          .fontColor($r('app.color.color_222222'))
          .visibility(this.tabItem.hasRightTitle ? Visibility.Visible : Visibility.None)
      }
      Image($r('app.media.ic_arrow_right_gray_small'))
        .width(24)
        .margin({ left: 12 })
        .visibility(this.tabItem.hasRightIcon ? Visibility.Visible : Visibility.None)
    }
    .width(CommonConst.FULL_PARENT)
    .height(44)
    .backgroundColor($r('app.color.white'))
    .onClick(() => {
      this.onItemClick?.()
    })
  }
}


  • 3、使用案例
    3.1 针对于一个,可以用下面的代码,但是对于一个页面有多个的话,要是一行行的写,虽然可以,但是不建议,而且也不优雅,所以需要用到ForEach来实现。
  HorizontalTabItemComp({
        tabItem: new TabHorizontalModel("我的积分", 0, $r('app.media.ic_coin'), true),
        onItemClick: () => {
          ToastUtil.showToast('我的积分')
        }
      }).margin({ left: 12, right: 12 })

3.2 定义一组数据,塞到数组里

/** 横向Tab */
export const horizontalTabItemData: Array = [
  new TabHorizontalModel("我的积分", 0, $r('app.media.ic_coin'), true, '666', true),
  new TabHorizontalModel("我的分享", 1, $r('app.media.ic_share_article'), true),
  new TabHorizontalModel("我的收藏", 2, $r('app.media.ic_collect'), true),
  new TabHorizontalModel("我的书签", 3, $r('app.media.ic_read_later'), true),
  new TabHorizontalModel("阅读历史", 4, $r('app.media.ic_read_record'), true),
  new TabHorizontalModel("开源项目", 5, $r('app.media.ic_github'), true),
  new TabHorizontalModel("关于作者", 6, $r('app.media.ic_about'), true, '请他喝杯咖啡~', true),
]

3.3 使用ForEach来实现

 ForEach(horizontalTabItemData, (item: TabHorizontalModel, index: number) => {
        HorizontalTabItemComp({
          tabItem: item,
          onItemClick: () => {
            this.onItem

你可能感兴趣的:(HarmonyOS,NEXT,harmonyos)