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

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

相关文章:

  • OpenHarmony外设驱动使用 (十),Sensor
  • DeepSeek 的强化学习优化策略:RLHF 与 DPO 的应用
  • canvas(二)-动画(2d)
  • 如果有三个服务实例部署在三台不同的服务器上,这三个服务实例的本地缓存,是存储一模一样的数据?还是各自只存一部分?
  • 《算法笔记》12.1小节——字符串专题->字符串hash进阶 问题 A: 求最长公共子串(串)
  • vscode连接本地Ubuntu
  • Docker安装Fluentd采集中间件
  • OpenCV CUDA模块特征检测与描述------一种基于快速特征点检测和旋转不变的二进制描述符类cv::cuda::ORB
  • 嵌入式学习的第二十五天-系统编程-文件相关函数-标准I0+文件IO
  • 视觉生成新突破!仅0.5B参数,SimpleAR解锁预训练、SFT、RL全能模式
  • 使用 Vue 展示 Markdown 文本
  • 【Java高阶面经:微服务篇】7. 1秒响应保障:超时控制如何成为高并发系统的“救火队长”?
  • 期刊采编系统安装升级错误
  • 软考 系统架构设计师系列知识点之杂项集萃(66)
  • Nginx负载均衡配置详解
  • 回溯算法——排列篇
  • 阿里云ecs 8核 16G 内存 装有redis6 分配了3G内存,和2个tomcat 每个tomcat 4G 服务器反应迟钝,如何确认不是redis的问题
  • web.py使用时报错AttributeError: No template named image_window
  • RTMP协议解析【二】
  • 下一代电子电气架构(EEA)的关键技术
  • 做外贸有哪些好的免费b2b网站/网络营销的成功案例有哪些
  • 网站建设上海网站建设/在线培训课程
  • 精品课程网站建设方案/西安网站建设排名
  • 吴江企业建设网站/全网自媒体平台
  • 做乒乓球网站的图片大全/百度快速排名培训
  • 怎样在微信上做网站/seo网络培训班