HarmonyOS NEXT - Navigation组件封装BaseNavigation

news2024/12/24 9:29:04

demo 地址: https://github.com/iotjin/JhHarmonyDemo
代码不定时更新,请前往github查看最新代码

在demo中这些组件和工具类都通过module实现了,具体可以参考HarmonyOS NEXT - 通过 module 模块化引用公共组件和utils

官方介绍

组件导航 (Navigation)(推荐)

Navigation是路由容器组件,一般作为首页的根容器,包括单栏(Stack)、分栏(Split)和自适应(Auto)三种显示模式。Navigation组件适用于模块内和跨模块的路由切换,一次开发,多端部署场景。通过组件级路由能力实现更加自然流畅的转场体验,并提供多种标题栏样式来呈现更好的标题和内容联动效果。在不同尺寸的设备上,Navigation组件能够自适应显示大小,自动切换分栏展示效果。

Navigation组件主要包含​导航页(NavBar)和子页(NavDestination)。导航页由标题栏(Titlebar,包含菜单栏menu)、内容区(Navigation子组件)和工具栏(Toolbar)组成,其中导航页可以通过hideNavBar属性进行隐藏,导航页不存在页面栈中,导航页和子页,以及子页之间可以通过路由操作进行切换。

在API Version 9上,需要配合NavRouter组件实现页面路由,从API Version 10开始,推荐使用NavPathStack实现页面路由。

这里里封装的只是组件,路由跳转通过 Router切换Navigation 或者 @ohos.route 跳转
demo中都是通过@ohos.router实现的跳转,因为Router需要Navigation 包着页面的内容,多一层嵌套

页面路由 (@ohos.router)(不推荐)
Router切换Navigation

Navigation官方效果图

请添加图片描述

BaseNavigation效果图

请添加图片描述

Navigation使用

@Entry
@Component
struct TestNav {
  // menus(value: Array<NavigationMenuItem> | CustomBuilder): NavigationAttribute

  aboutToAppear() {
    console.log('CustomComponent: aboutToAppear called. Component is about to appear.')
    // 在这里执行初始化数据的操作
  }

  build() {
    Column() {
      this.NavigationTest()
    }
  }

  TooTmp: NavigationMenuItem = {
    'value': "1",
    'action': () => {
    },
    'icon': "resources/rawfile/tab/nav_tab_1.png",
  }
  TooBar: ToolbarItem[] = [this.TooTmp, this.TooTmp, this.TooTmp]

  @Builder
  NavigationTest() {
    Navigation() {
      RelativeContainer() {
        Text('Content')
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
          .alignRules({
            center: { anchor: '__container__', align: VerticalAlign.Center },
            middle: { anchor: '__container__', align: HorizontalAlign.Center }
          })
      }
      .height('100%')
      .width('100%')
    }
    .titleMode(NavigationTitleMode.Mini)
    .title("标题栏") // 设置title,此时不支持修改文字大小,颜色等样式
    .hideBackButton(false)
    .menus([this.TooTmp, this.TooTmp, this.TooTmp])
    .toolbarConfiguration(this.TooBar)

    // .size({ width: '100%', height: '100%' })
    // .backgroundColor(Color.Orange)
    // .toolbarConfiguration(this.TooBar)
  }
}

BaseNavigation使用

demo里的弹框在这里 HarmonyOS NEXT - Toast和Loading使用

  • 左侧返回,右侧文字
BaseNavigation({
   title: '标题标题标题标题标题标题标题标题标题标题',
   rightText: '设置',
   rightItemCallBack: () => {
     console.log("点击了设置")
     JhProgressHUD.showText("点击了设置")
   }
 })
  • 左侧返回(拦截点击事件),右侧图片
  BaseNavigation({
    title: '标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题',
    titleTextAlign: TextAlign.Start,
    // rightImgPath: 'resources/rawfile/images/ic_more_white.png',
    rightImgPath: $rawfile("images/ic_nav_add.png"),
    rightItemCallBack: () => {
      JhProgressHUD.showText("点击了右侧图标")
    },
    leftItemCallBack: () => {
      JhProgressHUD.showText("点击左侧")
    }
  })
  • 左侧自定义右侧文字
  BaseNavigation({
    title: '标题',
    titleTextAlign: TextAlign.Start,
    leftItem: {
      text: '设置1',
      icon: $rawfile("images/ic_nav_add.png"),
      itemCallBack: () => {
        JhProgressHUD.showText("点击了左侧")
      }
    },
    rightText: '发布',
    rightItemCallBack: () => {
      console.log("点击了设置")
      JhProgressHUD.showText("点击了发布")
    }
  })
  • 渐变导航条
BaseNavigation({
   isGradient: true,
   title: '标题',
   // rightImgPath: 'resources/rawfile/images/ic_more_white.png',
   rightImgPath: $rawfile("images/ic_nav_add.png"),
   rightItemCallBack: () => {
     JhProgressHUD.showText("点击了右侧图标")
   }
 })
  • 右侧自定义1
     BaseNavigation({
       title: '标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题',
       titleTextAlign: TextAlign.Start,
       rightItems: [
         {
           text: '设置1',
           itemCallBack: () => {
             JhProgressHUD.showText("点击了设置1")
           }
         },
         {
           text: '设置2',
           itemCallBack: () => {
             JhProgressHUD.showText("点击了设置2")
           }
         }
       ]
     })
  • 内部包裹child内容
 BaseNavigation({
    title: '自定义child',
    child: () => {
      this.childBuilder()
    }
  })

  @Builder
  childBuilder() {
    Scroll() {
      Column() {
        Text('111111111')
          .width('100%')
          .height(600)
          .backgroundColor(Color.Orange)
        Text('222222222')
          .width('100%')
          .height(500)
          .backgroundColor(Color.Yellow)
      }
    }
  }

JhProgressHud.ets 完整代码

///  BaseNavigation.ets
///
///  Created by iotjin on 2024/08/01.
///  description: 导航条

import { router } from '@kit.ArkUI';
import { KColors } from '../configs/Colors';

type imageType = string | Resource | PixelMap

interface ItemType {
  icon?: imageType // icon优先级高于text
  text?: string
  itemCallBack?: () => void
}

const _titleFontSize = 18.0
const _textFontSize = 16.0
const _itemSpace = 15.0 // 右侧item内间距
const _imgWH = 22.0 // 右侧图片宽高
const _rate = 16 // 左右item占比

const _bgColor: ResourceColor = KColors.kThemeColor
const _bgDarkColor: ResourceColor = KColors.kNavBgDarkColor
const _titleColor: ResourceColor = KColors.kNavTitleColor

const _appbarStartColor = KColors.kGradientStartColor // 默认appBar 渐变开始色
const _appbarEndColor = KColors.kGradientEndColor // 默认appBar 渐变结束色

@Preview
@Component
export struct BaseNavigation {
  @Prop public title: string = '' // 标题文字
  private isCenterTitle: boolean = true
  @Prop public titleFontSize: number = _titleFontSize
  @Prop public titleTextAlign: TextAlign = this.isCenterTitle ? TextAlign.Center : TextAlign.Start
  @Prop public bgColor: ResourceColor = _bgColor
  @Prop public leftItem?: ItemType | null = null // 左侧Widget,为空显示返回按钮
  public leftItemCallBack?: () => void
  @Prop public rightText: string = '' // 右侧按钮文字
  @Prop public rightImgPath: imageType = '' // 右侧按钮图片路径,优先级高于text ,eg: $rawfile("images/ic_nav_add.png") | 'resources/rawfile/images/ic_nav_add.png'
  public rightItemCallBack?: () => void
  @Prop public rightItems: [] | [ItemType] | [ItemType, ItemType] = [] // 优先级高于rightText和rightImgPath
  @Prop public isGradient: boolean = false // 是否渐变背景色
  @Prop public navHeight: number = 56 // 传入child为100%,否则为navHeight
  @BuilderParam child?: () => void // 子组件
  //
  private backImage: imageType = $rawfile("common/ic_nav_back_white.png")
  private titleAndIconColor: ResourceColor = _titleColor

  aboutToAppear() {
    // 如果背景透明或者是白色,设置字体和图标、状态栏字体为黑色
    let isTransparent = this.bgColor == Color.Transparent || this.bgColor == Color.White || this.bgColor == KColors.kNavWhiteBgColor
    if (isTransparent) {
      this.titleAndIconColor = Color.Black
      this.backImage = $rawfile("common/ic_nav_back_black.png")
    }
  }

  build() {
    Navigation() {
      if (this.child) {
        this.child()
      }
    }
    .titleMode(NavigationTitleMode.Mini)
    .title(this.NavigationTitle())
    .hideBackButton(true)
    .height(this.child ? '100%' : this.navHeight)
  }

  @Builder
  NavigationTitle() {
    Row() {
      this.navBuilder()
    }
    .width('100%')
    .height('100%')
    .backgroundColor(this.bgColor)
    .linearGradient(this.isGradient ? {
      direction: GradientDirection.Right, // 从左向右
      colors: [[_appbarStartColor, 0.0], [_appbarEndColor, 1.0]]
    } : null)
  }

  @Builder
  navBuilder() {
    Row() {
      if (this.leftItem) {
        Row() {
          this.itemBuilder({ icon: this.leftItem.icon, text: this.leftItem.text })
        }.onClick(this.leftItem.itemCallBack)
      } else {
        this.backBuilder()
      }
    }
    .layoutWeight(_rate)
    .width('100%')

    Row() {
      this.titleBuilder()
    }
    .layoutWeight(this.rightItems.length ? (100 - _rate - this.rightItems.length * _rate) : (100 - _rate * 2))
    .width('100%')

    if (this.rightItems.length) {
      Row() {
        ForEach(this.rightItems, (item: ItemType) => {
          Row() {
            this.itemBuilder({ icon: item.icon, text: item.text })
          }.onClick(item.itemCallBack)
          .layoutWeight(1)
          .width('100%')
        })
      }
      .margin({ left: this.rightItems.length == 2 ? 15 : 0, right: this.rightItems.length == 2 ? 5 : 0 })
      .layoutWeight(_rate * this.rightItems.length)
      .width('100%')
    } else {
      Row() {
        this.itemBuilder({ icon: this.rightImgPath, text: this.rightText })
      }
      .onClick(this.rightItemCallBack)
      .layoutWeight(_rate)
      .width('100%')
    }
  }

  @Builder
  backBuilder() {
    Row() {
      Image(this.backImage)
        .width(18)
        .height(18)
        .margin({ left: 15 })
    }
    .size({ width: '100%', height: '100%' })
    .onClick(() => {
      if (this.leftItemCallBack) {
        this.leftItemCallBack()
      } else {
        this.goBack()
      }
    })
  }

  @Builder
  titleBuilder() {
    Row() {
      Text(this.title)
        .padding({
          left: 10,
          top: 5,
          right: 10,
          bottom: 5
        })
        .fontSize(this.titleFontSize)
        .fontColor(this.titleAndIconColor)
        .textAlign(this.titleTextAlign)
        .maxLines(2)
        .textOverflow({ overflow: TextOverflow.Ellipsis })// 文本超长显示省略号
        .wordBreak(WordBreak.BREAK_WORD)
    }
    .justifyContent(FlexAlign.Center)
    .alignItems(VerticalAlign.Center)
    .size({ width: '100%', height: '100%' })
  }

  @Builder
  itemBuilder(item: ItemType) {
    Row() {
      if (item.icon) {
        Image(item.icon)
          .width(_imgWH)
          .height(_imgWH)
          .margin({ left: _itemSpace, right: _itemSpace })
      } else if (item.text) {
        Text(item.text)
          .fontSize(_textFontSize)
          .fontColor(this.titleAndIconColor)
      }
    }
    .size({ width: '100%', height: '100%' })
    .justifyContent(FlexAlign.Center)
    .alignItems(VerticalAlign.Center)
  }

  goBack() {
    router.back()
  }
}

里面用到的颜色

export class KColors {
  // 主题色(导航条背景、提交按钮背景、弹框确认文字、表单图标录入光标)
  // 暗黑模式高亮显示颜色按kThemeColor设置,如tabBar选中文字图标、提交按钮背景色、指示器选中下划线、光标等
  static readonly kThemeColor: ResourceColor = '#3BB815'
  static readonly kThemeDarkColor: ResourceColor = '#0A0A0A' // (10, 10, 10)
  static readonly kThemeBlueColor: ResourceColor = '#4688FA'
  static readonly kThemePurpleColor: ResourceColor = '#9C27B0'
  // 渐变色(appBar和按钮)
  static readonly kGradientStartColor: ResourceColor = '#2683BE' // 渐变开始色
  static readonly kGradientEndColor: ResourceColor = '#34CABE' // 渐变结束色
  static readonly kNavTitleColor: Color = Color.White
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2048146.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

​【迅为电子】RK3568驱动指南|第十七篇 串口-第197章 串口通信协议

瑞芯微RK3568芯片是一款定位中高端的通用型SOC&#xff0c;采用22nm制程工艺&#xff0c;搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码&#xff0c;支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU&#xff0c;可用于轻量级人工…

vue3 ts 集成 supermap

文章目录 1. 依赖安装2. 模块声明3. css 全局引入4. 地图加载 1. 依赖安装 npm install supermapgis/iclient-leafletnpm install leaflet2. 模块声明 env.d.ts declare module leaflet {const L: any;export default L; }declare module supermapgis/iclient-leaflet3. css …

高数3.5 极值与最值

1. 极值 1.1. 定义 1.2. 推论 1.3. 求极值的步骤 1.3.1 方法1 1.3.1.1 例题

BCLinux8.*构建部署nmap 7.95

定义SPEC文件 首先从nmap的github上下载SPEC定义文件&#xff0c;然后进行修改&#xff0c;如下&#xff1a; # To build a static RPM, add # --define "static 1" # to the rpmbuild command line. To build without Ncat, add # --define "buildnc…

FastHTML:使用 Python 彻底改变 Web 开发

什么是 FastHTML&#xff1f;&#x1f310; FastHTML 是一个现代 Python Web 应用程序框架&#xff0c;其真正目的是让 Python 开发人员轻松进行 Web 开发。它大大减少了对 JavaScript 和 CSS 构建交互式和可扩展 Web 应用程序的依赖。FastHTML 通过使用 Python 对象来表示 HTM…

centos虚拟机IP地址频繁变化的原因及解决策略

文章目录 centos虚拟机IP地址频繁变化的原因及解决策略虚拟机IP地址变化的原因解决虚拟机IP地址变化的策略1. 使用静态IP地址Windows系统&#xff1a;Linux系统&#xff1a; 2. 配置DHCP保留3. 使用虚拟化平台的网络功能4. 检查和更新网络驱动程序5. 优化网络配置脚本6. 监控和…

BIO,NIO,AIO编程实战

写在前面 关于IO分类以及IO模型等理论知识&#xff0c;可以参考io之io分类和io模型这篇文章。本文主要来实现Java中相关IO模型实现程序。 1&#xff1a;BIO blocking io&#xff0c;是Java io中对阻塞IO模型的具体实现。 因为不管是server端还是client端&#xff0c;都需要…

JavaSE的【反射】和【动态代理】

作为JavaSE的两个个基础知识&#xff0c;【反射】和【动态代理】被广泛运用到spring、spring boot、mybatis......等等各种地方&#xff0c;等到后面的学习中反复提到这个知识点就会开始懵逼&#xff0c;而且这两个知识点其实也是紧密相连的&#xff0c;很多文章和课程里也并没…

零基础STM32单片机编程入门(三十七) MPU6050陀螺仪传感器详解及实战源码

文章目录 一.概要二.MPU6050芯片介绍1.MEMS传感器原理2.MPU6050芯片简介3.芯片引脚定义4.XYZ轴方向5.芯片内部框图6.芯片常用寄存器 三.MPU6050模块原理图及与模块接口定义使用四.STM32单片机驱动MPU6050读取加速度角速度值实验五.CubeMX工程源代码下载六.小结 一.概要 MPU605…

嵌入式面经篇六——寄存器与存储器

文章目录 前言一、寄存器与存储器1、ARM 的 31 个通用寄存器 R0~R15 中&#xff0c;程序计数器 PC 为 R15、程序链接寄存器 LR 为 R14、堆栈指针寄存器 SP 为 R13。2、寄存器掉电会丢失数据吗&#xff1f;3、NOR Flash 与 NAND Flash 的区别&#xff1f;4、SRAM、DRAM、SDRAM的…

使用Python创建省份城市地图选择器

在这篇博客中&#xff0c;我们将探讨如何使用Python创建一个简单而实用的省份城市地图选择器。这个项目不仅能帮助我们学习Python的基础知识&#xff0c;还能让我们了解如何处理JSON数据和集成网页浏览器到桌面应用程序中。 C:\pythoncode\new\geographicgooglemap.py 全部代码…

Camtasia 2024破解版安装教程+汉化补丁激活2024 破解版激活码

最近&#xff0c;我在网上冲浪的时候&#xff0c;发现了一款录屏软件——Camtasia 2024。它不仅功能丰富&#xff0c;而且操作简单&#xff0c;简直是我的录屏利器&#xff01;今天&#xff0c;我就来给大家分享一下这款软件的最新功能&#xff0c;让你们也感受一下它的魔力&am…

【LeetCode:3137. K 周期字符串需要的最少操作次数 | 哈希表 + 子串计数】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

政务网站(.gov)专用SSL/HTTPS证书

政府网站在选择SSL证书时不仅需要遵循网络安全法规以及密评整改&#xff0c;更要提升公众信任度。国产服务商提供的专业版SSL证书&#xff0c;全方位符合政务部门对SSL证书的要求 1 算法要求 政务服务网站需要落实等保制度、密评制度&#xff0c;在密码应用上可选择国密算法S…

从0到1教你搭建Android自动化python+appium环境(超详细~)

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、需要软件 1. JDK:JAVA安装后配置JDK环境 2. SDK:SDK下载后配置adb环境 3. Python:pyhton语言 4. Pycharm:python脚本编译工具 5. Appium-python-clien…

如何巧妙构建“LDAPS”服务器利用JNDI注入

前段时间看到群友问了这样一个问题&#xff1a; ldap:和rmi:关键字被拦截了&#xff0c;是否还可以进行JNDI注入。方法很简单&#xff0c;就是使用ldaps&#xff0c;但后来发现很多人并不知道怎么搭建LDAPS服务器&#xff0c;正好CoNote里有这个功能&#xff0c;写篇简单的文章…

【大模型】LLM工作原理简述

LLM&#xff0c;即large-language-model&#xff0c;大语言模型。 我们可以观察LLM大模型比如豆包在回复的时候&#xff0c;是不是一个一个字&#xff0c;行业里称之为流式输出的方式给你呈现内容的。为什么会这样呢&#xff1f;这是因为&#xff0c;大模型确实是在一个字一个…

Libero编译怪事(1)计数达不到目标值

最近在开发Libero工程&#xff0c;芯片是AGLN250V2。 其中一段计数的程序&#xff0c;声明了一个integer参数。当该参数大于某一值时&#xff0c;执行状态跳转。 编译烧写后&#xff0c;程序一直无法实现跳转。 以为是由于integer是有符号的&#xff0c;可能出现负值&#x…

IDEA中查看接口的所有实现类和具体实现类

1.IDEA中接口的所有实现类查看 1.CTRLH(hierarchy 结构) 我们选中要查看的接口 按住快捷键ctrlh 在界面右侧可以看到该接口的所有可能实现类 2.右击diagrams->show diagram 选中要查看的接口 右击选择diagrams->show diagram 即可以以图表的方式查看接口和所有实现类…

英智金融行业AI Agent,在金融领域全场景下的业务创新与应用实践

随着全球经济的数字化转型&#xff0c;金融行业也在迅速演变。传统的金融服务已经无法完全满足现代客户对快速、个性化和高效服务的需求。与此同时&#xff0c;市场竞争的加剧、监管环境的变化以及客户期望的提升&#xff0c;促使金融机构不断寻求新的技术来优化运营效率、提升…