1.方案一
CustomNavigationBar
TypeScript
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.White
private context = getContext(this) as common.UIAbilityContext;
onHeightChange?: (height: number) => void
aboutToAppear() {
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
TypeScript
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.White
private context = getContext(this) as common.UIAbilityContext;
onHeightChange?: (height: number) => void
aboutToAppear() {
DevicesUtil.getStatusBarHeight(this.context).then(height => {
this.statusBarHeight = height
this.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.工具
获取状态栏高度
TypeScript
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.使用示例
跳转协议
TypeScript
/// 用户隐私协议
private userPrivacyPolicy() {
router.pushUrl({
url: 'pages/features/protocol/MFProtocolView',
params: {
webUrl: 'https://www.baidu.com',
title: '隐私协议'
}
})
}
协议页面
注意:方案二会导致页面底部超出屏幕,所以需要设置.margin({bottom: this.navHeight})
TypeScript
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(()=>{
})
}
}