当前位置: 首页 > ops >正文

[Harmony]自定义导航栏

1.方案一

CustomNavigationBar


import { router } from '@kit.ArkUI';
import { DevicesUtil } from '../utils/DevicesUtil';
import { common } from '@kit.AbilityKit';@Component
export struct CustomNavigationBar {@State private navHeight: number = 44@State parTitle: string = ''@State parBGColor: Color = Color.Whiteprivate context = getContext(this) as common.UIAbilityContext;onHeightChange?: (height: number) => voidaboutToAppear() {DevicesUtil.getStatusBarHeight(this.context).then(height => {this.onHeightChange?.(height + this.navHeight) // 触发回调})}build() {Column({ space:0 }) {Stack(){Row({ space: 0 }) {Image($r('app.media.icon_base_back')).objectFit(ImageFit.Contain).width(44).height(44).padding(12).onClick(() => router.back())Image($r('app.media.icon_nav_logo')).objectFit(ImageFit.Contain).width(64).height(44).padding({ right: 10 })}.width('100%').justifyContent(FlexAlign.SpaceBetween).backgroundColor(Color.Transparent)Row({ space: 0 }) {Text(this.parTitle).fontSize(17).fontColor($r('app.color.mf_base_333333')).fontWeight(FontWeight.Bold)}.justifyContent(FlexAlign.Center).backgroundColor(Color.Transparent)}.width('100%').height(this.navHeight)}.width('100%').backgroundColor(this.parBGColor).expandSafeArea( [SafeAreaType.SYSTEM], [SafeAreaEdge.TOP] )}}

示意图

2.方案二

CustomNavigationBar


import { router, window } from '@kit.ArkUI';
import { DevicesUtil } from '../utils/DevicesUtil';
import { common } from '@kit.AbilityKit';@Component
export struct CustomNavigationBar {@State private statusBarHeight: number = 24 // 默认值(vp)@State private navHeight: number = 44@State parTitle: string = ''@State parBGColor: Color = Color.Whiteprivate context = getContext(this) as common.UIAbilityContext;onHeightChange?: (height: number) => voidaboutToAppear() {DevicesUtil.getStatusBarHeight(this.context).then(height => {this.statusBarHeight = heightthis.onHeightChange?.(height + this.navHeight) // 触发回调})}build() {Column({ space:0 }) {// 状态栏占位区域Row().width('100%').height(this.statusBarHeight).backgroundColor(Color.Transparent)// 导航内容区域Stack(){Row({ space: 0 }) {Image($r('app.media.icon_base_back')).objectFit(ImageFit.Contain).width(44).height(44).padding(12).onClick(() => router.back())Image($r('app.media.icon_nav_logo')).objectFit(ImageFit.Contain).width(64).height(44).padding({ right: 10 })}.width('100%').justifyContent(FlexAlign.SpaceBetween).backgroundColor(Color.Transparent)Row({ space: 0 }) {Text(this.parTitle).fontSize(17).fontColor($r('app.color.mf_base_333333')).fontWeight(FontWeight.Bold)}.justifyContent(FlexAlign.Center).backgroundColor(Color.Transparent)}.width('100%').height(this.navHeight)}.width('100%').backgroundColor(this.parBGColor).expandSafeArea( [SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM] ).onAppear(async ()=>{window.getLastWindow(this.context).then(win => {win.setWindowLayoutFullScreen(true) // 隐藏系统栏// win.setWindowSystemBarEnable(['navigation']) // 可选控制导航栏显示//这一句不设置 不然第二次进入是就没状态栏那一行了})})}}

示意图

3.工具

获取状态栏高度

import window from '@ohos.window';
import { common } from '@kit.AbilityKit';export class DevicesUtil {/// 状态栏高度static async getStatusBarHeight(context: common.UIAbilityContext, isVP: boolean = true): Promise<number> {try {const win = await window.getLastWindow(context);/*getWindowAvoidArea返回的物理像素,需要转换为虚拟像素返回,便于布局TYPE_SYSTEM:获取状态栏区域(推荐使用)TYPE_NAVIGATION_INDICATOR:获取导航栏区域TYPE_CUTOUT:获取刘海屏区域*/const avoidArea = await win.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM);if (isVP) {return DevicesUtil.pxToVp(avoidArea.topRect.height);} else {return avoidArea.topRect.height;}} catch {return isVP ? 24 : 96; // 默认安全高度 // 96 假设480dpi设备}}
}

4.使用示例

跳转协议

/// 用户隐私协议
private userPrivacyPolicy() {router.pushUrl({url: 'pages/features/protocol/MFProtocolView',params: {webUrl: 'https://www.baidu.com',title: '隐私协议'}})
}

协议页面

注意:方案二会导致页面底部超出屏幕,所以需要设置.margin({bottom: this.navHeight})

import { router } from '@kit.ArkUI';
import { webview } from '@kit.ArkWeb';
import { CustomNavigationBar } from '../../../support/custom/CustomNavigationBar';
import ConsoleLog from '../../../support/extension/ConsoleLog';interface MFProtocolParams {webUrl: string;title?: string;
}@Entry
@Component
struct MFProtocolView {@State webUrl: string = ''; // 接收的网页地址@State title: string = '详情'; // 导航栏标题private controller: webview.WebviewController = new webview.WebviewController();@State private navHeight: number = 68 // 默认值(vp)aboutToAppear() {// 在aboutToAppear生命周期中读取路由参数const params: MFProtocolParams = router.getParams() as MFProtocolParams;if (params) {this.webUrl = params.webUrl || 'about:blank'; // 默认为空页面this.title = params.title || this.title; // 默认为'协议详情'}}build() {Column() {// 使用自定义导航栏组件CustomNavigationBar({ parTitle: this.title, parBGColor: Color.Red, onHeightChange: (height)=>{this.navHeight = height}})// 必须传递完整WebOptions参数Web({src: this.webUrl,controller: this.controller}).flexGrow(1) // 自动填充剩余空间.margin({bottom: this.navHeight}) // 方案一不用这行代码,方案二需要这行.onPageBegin((event) => {ConsoleLog.log('开始加载:' + event.url);})}.width('100%').height('100%').backgroundColor(Color.Green).onAppear(()=>{})}
}

http://www.xdnf.cn/news/7810.html

相关文章:

  • 【Java基础笔记vlog】Java中常见的几种数组排序算法汇总详解
  • 算法分析与设计实验:找零钱问题的贪心算法与动态规划解决方案
  • Nginx网站服务
  • AI+MCP 自动发布小红书笔记
  • 【基础】Windows开发设置入门9:WSL 2 上的 Docker 容器
  • 基于Go语言的恶意软件通过Redis配置滥用向Linux主机部署XMRig挖矿程序
  • [论文精读]Ward: Provable RAG Dataset Inference via LLM Watermarks
  • 数据库健康监测器(BHM)实战:如何通过 HTML 报告识别潜在问题
  • Android OkHttp控制链:深入理解网络请求的流程管理
  • 动手学习深度学习V1.1 chapter2 (2.1-2.2)
  • 读一本书第一遍是快读还是细读?
  • 物理机做完bond后network服务重启失败
  • IntelliJ IDEA 接入 DeepSeek帮助你更好编码
  • net Core》》包与库 LibMan、NPM
  • 从加密到信任|密码重塑车路云一体化安全生态
  • 【Redis】二、Redis常用数据类型命令学习
  • 电感在断开的时候会按原来的电流方向流动这是什么定理?
  • Baklib内容中台的构建要点是什么?
  • 【性能测试】jvm监控
  • 前端JavaScript学习-动态编码-基础
  • 【每周一个MCP】:将pytdx封装成MCP
  • NFM算法解析:如何用神经网络增强因子分解机的特征交互能力?
  • 基于Qt的app开发第十天
  • 每日leetcode
  • opencv的图像卷积
  • 物联网相关词汇
  • Pandas:数据分析步骤、分组函数groupby和基础画图
  • matlab二维随机海面模拟
  • C++之模板进阶(探索C++模板:非类型参数与特化技巧)
  • Linux网络 网络基础一