文章目录
-
- 每日一句正能量
- [一、前言:HarmonyOS 6的视觉革命](#一、前言:HarmonyOS 6的视觉革命)
- 二、核心特性解析
-
- [2.1 悬浮导航(Float Navigation)](#2.1 悬浮导航(Float Navigation))
- [2.2 沉浸光感(Immersive Light Effects)](#2.2 沉浸光感(Immersive Light Effects))
- 三、实战案例:打造沉浸式音乐播放器
-
- [3.1 项目配置](#3.1 项目配置)
- [3.2 窗口沉浸配置(EntryAbility.ets)](#3.2 窗口沉浸配置(EntryAbility.ets))
- [3.3 悬浮导航组件(FloatNavigation.ets)](#3.3 悬浮导航组件(FloatNavigation.ets))
- [3.4 沉浸光感音乐播放器页面(MusicPlayerPage.ets)](#3.4 沉浸光感音乐播放器页面(MusicPlayerPage.ets))
- [3.5 主入口页面集成(Index.ets)](#3.5 主入口页面集成(Index.ets))
- 四、关键技术总结
-
- [4.1 悬浮导航适配清单](#4.1 悬浮导航适配清单)
- [4.2 沉浸光感最佳实践](#4.2 沉浸光感最佳实践)
- 五、调试与测试建议
- 六、结语

每日一句正能量
不要去追一匹马,用追马的时间种草,待到春暖花开时,就会有一群骏马任你挑选;丰富自己,比取悦他人更有力量。早安!
一、前言:HarmonyOS 6的视觉革命
HarmonyOS 6(API 23)带来了令人惊艳的UI革新,其中**悬浮导航(Float Navigation)与沉浸光感(Immersive Light Effects)**两大特性成为开发者关注的焦点。这些特性不仅引入了半透明的毛玻璃视觉效果,还提供了底部悬浮导航栏,支持强、平衡、弱三档透明度自定义,让应用界面更具现代感和沉浸感。
本文将深入解析这两个核心特性,通过完整的代码实战,帮助开发者快速掌握HarmonyOS 6的视觉设计新范式。
二、核心特性解析
2.1 悬浮导航(Float Navigation)
悬浮导航是HarmonyOS 6引入的全新底部导航交互模式,主要特点包括:
- 悬浮层级设计:导航栏悬浮于内容之上,不占用布局空间
- 智能避让机制:内容区域自动适配导航栏高度,避免遮挡
- 动态透明度:支持根据滑动状态动态调整导航栏透明度
- 手势融合:与系统全面屏手势无缝衔接
2.2 沉浸光感(Immersive Light Effects)
沉浸光感是HarmonyOS 6的视觉增强系统,核心能力包括:
- P3广色域支持:色彩表现更丰富鲜艳
- 安全区布局优化:组件背景默认延伸至非安全区(AI导航栏、状态栏)
- 玻璃拟态效果:支持半透明、磨砂玻璃等现代视觉效果
- 系统级光效同步:锁屏、主屏、控制面板、通知面板光效统一
三、实战案例:打造沉浸式音乐播放器
本案例将构建一个具有悬浮导航和沉浸光感效果的音乐播放器应用,展示HarmonyOS 6新特性的完整开发流程。
3.1 项目配置
首先,在module.json5中声明必要的权限:
json
{
"module": {
"name": "entry",
"type": "entry",
"description": "$string:module_desc",
"mainElement": "EntryAbility",
"deviceTypes": [
"phone",
"tablet"
],
"pages": "$profile:main_pages",
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets",
"description": "$string:EntryAbility_desc",
"icon": "$media:layered_image",
"label": "$string:EntryAbility_label",
"startWindowIcon": "$media:startIcon",
"startWindowBackground": "$color:start_window_background",
"exported": true,
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
]
}
],
"requestPermissions": [
{
"name": "ohos.permission.SYSTEM_FLOAT_WINDOW",
"reason": "$string:float_window_permission",
"usedScene": {
"abilities": [
"EntryAbility"
],
"when": "always"
}
},
{
"name": "ohos.permission.INTERNET",
"reason": "$string:internet_permission"
}
]
}
}
3.2 窗口沉浸配置(EntryAbility.ets)
在Ability中配置窗口的沉浸模式,这是实现沉浸光感的基础:
typescript
// entry/src/main/ets/entryability/EntryAbility.ets
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
export default class EntryAbility extends UIAbility {
private windowStage: window.WindowStage | null = null;
onWindowStageCreate(windowStage: window.WindowStage): void {
this.windowStage = windowStage;
// 加载主页面
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
console.error('Failed to load content:', JSON.stringify(err));
return;
}
console.info('Succeeded in loading content.');
// 配置沉浸窗口
this.setupImmersiveWindow(windowStage);
});
}
private async setupImmersiveWindow(windowStage: window.WindowStage): Promise<void> {
try {
const mainWindow = windowStage.getMainWindowSync();
// 1. 设置窗口全屏布局,内容延伸至状态栏和导航栏
await mainWindow.setWindowLayoutFullScreen(true);
// 2. 设置窗口背景为透明,允许光效穿透
await mainWindow.setWindowBackgroundColor('#00000000');
// 3. 配置系统栏属性:透明背景+白色内容
await mainWindow.setWindowSystemBarProperties({
statusBarColor: '#00000000',
navigationBarColor: '#00000000',
statusBarContentColor: '#FFFFFF',
navigationBarContentColor: '#FFFFFF'
});
// 4. 启用安全区避让(关键:HarmonyOS 6新特性)
await mainWindow.setWindowAvoidAreaOption({
type: window.AvoidAreaType.TYPE_SYSTEM,
enabled: true
});
console.info('Immersive window setup completed');
} catch (error) {
console.error('Failed to setup immersive window:', (error as BusinessError).message);
}
}
onWindowStageDestroy(): void {
this.windowStage = null;
}
}
代码亮点 :上述代码通过setWindowLayoutFullScreen(true)实现内容延伸至非安全区,配合setWindowAvoidAreaOption启用HarmonyOS 6新增的安全区避让机制,确保悬浮导航不会遮挡关键内容。
3.3 悬浮导航组件(FloatNavigation.ets)
封装可复用的悬浮导航组件,支持动态透明度调节:
typescript
// entry/src/main/ets/components/FloatNavigation.ets
import { window } from '@kit.ArkUI';
// 透明度档位枚举
export enum TransparencyLevel {
STRONG = 0.85, // 强效果:高透明度,玻璃感明显
BALANCED = 0.70, // 平衡效果:适中透明度
WEAK = 0.55 // 弱效果:低透明度,更清晰
}
@Component
export struct FloatNavigation {
@State currentIndex: number = 0;
@State navTransparency: number = TransparencyLevel.BALANCED;
@State isExpanded: boolean = false;
@State bottomAvoidHeight: number = 0;
// 导航项配置
private navItems: Array<{icon: Resource, label: string, page: string}> = [
{ icon: $r('app.media.ic_home'), label: '首页', page: 'Home' },
{ icon: $r('app.media.ic_discover'), label: '发现', page: 'Discover' },
{ icon: $r('app.media.ic_library'), label: '音乐库', page: 'Library' },
{ icon: $r('app.media.ic_profile'), label: '我的', page: 'Profile' }
];
aboutToAppear(): void {
// 获取底部安全区高度(导航栏避让)
this.getBottomAvoidArea();
}
private async getBottomAvoidArea(): Promise<void> {
try {
const mainWindow = await window.getLastWindow();
const avoidArea = mainWindow.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR);
this.bottomAvoidHeight = avoidArea.bottomRect.height;
} catch (error) {
console.error('Failed to get avoid area:', error);
}
}
build() {
Stack({ alignContent: Alignment.Bottom }) {
// 内容区域(由父组件传入)
// 使用安全区底部避让,确保内容不被导航栏遮挡
Column() {
// 插槽:页面内容
this.contentBuilder()
}
.padding({ bottom: this.bottomAvoidHeight + 80 }) // 80为导航栏高度
// 悬浮导航栏容器
Column() {
// 玻璃拟态背景层
Stack() {
// 背景模糊效果(HarmonyOS 6新特性)
Column()
.width('100%')
.height('100%')
.backgroundBlurStyle(BlurStyle.REGULAR) // 毛玻璃效果
.opacity(this.navTransparency)
.backdropFilter($r('sys.blur.20')) // 背景模糊滤镜
// 渐变光效层
Column()
.width('100%')
.height('100%')
.linearGradient({
direction: GradientDirection.Top,
colors: [
['rgba(255,255,255,0.1)', 0.0],
['rgba(255,255,255,0.05)', 1.0]
]
})
}
.width('100%')
.height('100%')
.borderRadius(24) // 圆角设计
.shadow({
radius: 20,
color: 'rgba(0,0,0,0.15)',
offsetX: 0,
offsetY: -4
})
// 导航项
Row() {
ForEach(this.navItems, (item: {icon: Resource, label: string, page: string}, index: number) => {
Column() {
Stack() {
Image(item.icon)
.width(24)
.height(24)
.fillColor(this.currentIndex === index ? '#FF6B6B' : '#666666')
.transition(TransitionEffect.OPACITY)
// 选中指示器光效
if (this.currentIndex === index) {
Column()
.width(40)
.height(40)
.backgroundColor('rgba(255,107,107,0.2)')
.borderRadius(20)
.blur(10) // 光晕模糊效果
.position({ x: -8, y: -8 })
}
}
.width(40)
.height(40)
Text(item.label)
.fontSize(11)
.fontColor(this.currentIndex === index ? '#FF6B6B' : '#999999')
.margin({ top: 4 })
}
.layoutWeight(1)
.onClick(() => {
this.currentIndex = index;
// 触发微震动反馈
this.triggerHapticFeedback();
})
})
}
.width('100%')
.height(80)
.padding({ left: 16, right: 16 })
.justifyContent(FlexAlign.SpaceAround)
// 透明度调节滑块(HarmonyOS 6特色功能)
if (this.isExpanded) {
Row() {
Text('透明度')
.fontSize(12)
.fontColor('#666666')
.margin({ right: 8 })
Slider({
value: this.navTransparency * 100,
min: 55,
max: 85,
step: 15,
style: SliderStyle.InSet
})
.width(120)
.onChange((value: number) => {
this.navTransparency = value / 100;
})
Text(`${Math.round(this.navTransparency * 100)}%`)
.fontSize(12)
.fontColor('#666666')
.margin({ left: 8 })
}
.width('100%')
.height(40)
.justifyContent(FlexAlign.Center)
.backgroundColor('rgba(255,255,255,0.5)')
.borderRadius({ topLeft: 12, topRight: 12 })
}
}
.width('92%')
.height(this.isExpanded ? 120 : 80)
.margin({ bottom: this.bottomAvoidHeight + 12, left: '4%', right: '4%' })
.animation({
duration: 300,
curve: Curve.Spring,
iterations: 1
})
.gesture(
LongPressGesture({ duration: 500 })
.onAction(() => {
this.isExpanded = !this.isExpanded;
})
)
}
.width('100%')
.height('100%')
}
// 内容构建器(由外部传入)
@BuilderParam contentBuilder: () => void = this.defaultContentBuilder;
@Builder
defaultContentBuilder(): void {
Column() {
Text('内容区域')
.fontSize(16)
.fontColor('#999999')
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
private triggerHapticFeedback(): void {
// 调用系统震动接口
try {
import('@kit.SensorServiceKit').then(sensor => {
sensor.vibrator.startVibration({
type: 'time',
duration: 50
}, {
id: 0
});
});
} catch (error) {
console.error('Haptic feedback failed:', error);
}
}
}
技术要点:
- 背景模糊效果 :使用
backgroundBlurStyle(BlurStyle.REGULAR)和backdropFilter实现HarmonyOS 6的玻璃拟态效果 - 安全区适配 :通过
getWindowAvoidArea获取底部导航指示器高度,动态调整内容区域padding - 三档透明度:通过Slider组件实现强(85%)、平衡(70%)、弱(55%)三档透明度调节
- 光效叠加 :使用
linearGradient和blur组合创建沉浸光感的选中指示器
3.4 沉浸光感音乐播放器页面(MusicPlayerPage.ets)
实现具有沉浸光感效果的音乐播放页面:
typescript
// entry/src/main/ets/pages/MusicPlayerPage.ets
import { FloatNavigation, TransparencyLevel } from '../components/FloatNavigation';
import { window } from '@kit.ArkUI';
interface Song {
id: number;
title: string;
artist: string;
cover: Resource;
duration: number;
dominantColor: string; // 专辑主色调,用于沉浸光效
}
@Entry
@Component
struct MusicPlayerPage {
@State currentSong: Song = {
id: 1,
title: '光年之外',
artist: 'G.E.M.邓紫棋',
cover: $r('app.media.album_cover_1'),
duration: 234,
dominantColor: '#FF6B6B'
};
@State isPlaying: boolean = false;
@State progress: number = 0;
@State topAvoidHeight: number = 0;
@State lightIntensity: number = 0.6; // 光效强度
private timer: number = -1;
aboutToAppear(): void {
this.getTopAvoidArea();
this.startProgressTimer();
}
aboutToDisappear(): void {
clearInterval(this.timer);
}
private async getTopAvoidArea(): Promise<void> {
try {
const mainWindow = await window.getLastWindow();
const avoidArea = mainWindow.getWindowAvoidArea(window.AvoidAreaType.TYPE_STATUS);
this.topAvoidHeight = avoidArea.topRect.height;
} catch (error) {
console.error('Failed to get top avoid area:', error);
}
}
private startProgressTimer(): void {
this.timer = setInterval(() => {
if (this.isPlaying) {
this.progress += 1;
if (this.progress >= this.currentSong.duration) {
this.progress = 0;
}
}
}, 1000);
}
// 格式化时间
private formatTime(seconds: number): string {
const mins = Math.floor(seconds / 60);
const secs = seconds % 60;
return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
}
build() {
FloatNavigation({
contentBuilder: () => {
this.playerContentBuilder()
}
})
}
@Builder
playerContentBuilder(): void {
Stack() {
// 第一层:动态沉浸光效背景(HarmonyOS 6核心特性)
Column() {
// 主光晕效果
Column()
.width(300)
.height(300)
.backgroundColor(this.currentSong.dominantColor)
.blur(120) // 大范围模糊创建光晕
.opacity(this.lightIntensity)
.position({ x: '50%', y: 200 })
.anchor('50%')
.shadow({
radius: 100,
color: this.currentSong.dominantColor,
offsetX: 0,
offsetY: 0
})
.animation({
duration: 4000,
curve: Curve.EaseInOut,
iterations: -1,
playMode: PlayMode.Alternate
})
.rotate({ angle: 360 })
// 辅助光效粒子
ForEach([1, 2, 3], (item: number) => {
Column()
.width(100 + item * 50)
.height(100 + item * 50)
.backgroundColor(this.currentSong.dominantColor)
.blur(80)
.opacity(0.3 - item * 0.05)
.position({
x: `${30 + item * 20}%`,
y: 400 + item * 100
})
})
}
.width('100%')
.height('100%')
.backgroundColor('#1a1a2e') // 深色背景增强光效对比
.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM]) // 关键:扩展至安全区
// 第二层:内容层
Column() {
// 顶部状态栏避让
Column()
.width('100%')
.height(this.topAvoidHeight)
// 头部
Row() {
Image($r('app.media.ic_back'))
.width(24)
.height(24)
.fillColor('#FFFFFF')
Text('正在播放')
.fontSize(18)
.fontColor('#FFFFFF')
.fontWeight(FontWeight.Medium)
Image($r('app.media.ic_more'))
.width(24)
.height(24)
.fillColor('#FFFFFF')
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
.padding(16)
// 专辑封面区域(带玻璃拟态边框)
Stack() {
// 背景光晕
Column()
.width(280)
.height(280)
.backgroundColor(this.currentSong.dominantColor)
.blur(40)
.opacity(0.5)
// 封面容器(玻璃拟态效果)
Column() {
Image(this.currentSong.cover)
.width(260)
.height(260)
.borderRadius(20)
.shadow({
radius: 30,
color: 'rgba(0,0,0,0.4)',
offsetX: 0,
offsetY: 10
})
.rotate({ angle: this.isPlaying ? 360 : 0 })
.animation({
duration: 20000,
curve: Curve.Linear,
iterations: -1,
playMode: PlayMode.Normal
})
}
.width(280)
.height(280)
.backgroundBlurStyle(BlurStyle.REGULAR) // 封面容器毛玻璃效果
.borderRadius(30)
.border({
width: 1,
color: 'rgba(255,255,255,0.2)',
style: BorderStyle.Solid
})
}
.margin({ top: 40 })
// 歌曲信息
Column() {
Text(this.currentSong.title)
.fontSize(24)
.fontColor('#FFFFFF')
.fontWeight(FontWeight.Bold)
.margin({ bottom: 8 })
Text(this.currentSong.artist)
.fontSize(16)
.fontColor('rgba(255,255,255,0.7)')
}
.margin({ top: 40 })
// 进度条(带光效)
Column() {
Slider({
value: this.progress,
min: 0,
max: this.currentSong.duration,
step: 1,
style: SliderStyle.OutSet
})
.width('90%')
.selectedColor(this.currentSong.dominantColor) // 进度条使用专辑主色
.blockColor('#FFFFFF')
.showSteps(false)
.onChange((value: number) => {
this.progress = value;
})
Row() {
Text(this.formatTime(this.progress))
.fontSize(12)
.fontColor('rgba(255,255,255,0.6)')
Text(this.formatTime(this.currentSong.duration))
.fontSize(12)
.fontColor('rgba(255,255,255,0.6)')
}
.width('90%')
.justifyContent(FlexAlign.SpaceBetween)
.margin({ top: 8 })
}
.margin({ top: 60 })
// 控制按钮
Row() {
// 上一首
Button() {
Image($r('app.media.ic_previous'))
.width(32)
.height(32)
.fillColor('#FFFFFF')
}
.type(ButtonType.Circle)
.backgroundColor('rgba(255,255,255,0.1)')
.width(60)
.height(60)
.backdropFilter($r('sys.blur.10')) // 按钮毛玻璃效果
// 播放/暂停
Button() {
Image(this.isPlaying ? $r('app.media.ic_pause') : $r('app.media.ic_play'))
.width(40)
.height(40)
.fillColor('#FFFFFF')
}
.type(ButtonType.Circle)
.backgroundColor(this.currentSong.dominantColor)
.width(80)
.height(80)
.shadow({
radius: 20,
color: this.currentSong.dominantColor,
offsetX: 0,
offsetY: 0
})
.onClick(() => {
this.isPlaying = !this.isPlaying;
})
// 下一首
Button() {
Image($r('app.media.ic_next'))
.width(32)
.height(32)
.fillColor('#FFFFFF')
}
.type(ButtonType.Circle)
.backgroundColor('rgba(255,255,255,0.1)')
.width(60)
.height(60)
.backdropFilter($r('sys.blur.10'))
}
.width('100%')
.justifyContent(FlexAlign.SpaceEvenly)
.margin({ top: 40 })
Blank() // 填充剩余空间
}
.width('100%')
.height('100%')
}
.width('100%')
.height('100%')
}
}
沉浸光感实现要点:
- 动态光晕背景 :使用专辑主色调配合大范围
blur(120)创建呼吸灯效果的光晕背景 - 安全区扩展 :通过
expandSafeArea方法将背景延伸至状态栏和底部区域,实现全屏沉浸 - 玻璃拟态组件 :封面容器和控制按钮使用
backgroundBlurStyle和backdropFilter实现毛玻璃质感 - P3广色域适配:使用高饱和度颜色值,HarmonyOS 6会自动在支持P3色域的设备上呈现更鲜艳的色彩
3.5 主入口页面集成(Index.ets)
typescript
// entry/src/main/ets/pages/Index.ets
import { FloatNavigation } from '../components/FloatNavigation';
import { router } from '@kit.ArkUI';
@Entry
@Component
struct Index {
@State currentPage: number = 0;
build() {
FloatNavigation({
currentIndex: this.currentPage,
contentBuilder: () => {
this.pageContentBuilder()
}
})
}
@Builder
pageContentBuilder(): void {
Tabs({ barPosition: BarPosition.Start, index: this.currentPage }) {
TabContent() {
HomePage()
}
TabContent() {
DiscoverPage()
}
TabContent() {
LibraryPage()
}
TabContent() {
ProfilePage()
}
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
.onChange((index: number) => {
this.currentPage = index;
})
}
}
四、关键技术总结
4.1 悬浮导航适配清单
| 适配项 | API/方法 | 说明 |
|---|---|---|
| 获取安全区高度 | window.getWindowAvoidArea() |
HarmonyOS 6支持多种避让类型 |
| 背景模糊效果 | backgroundBlurStyle() |
系统级毛玻璃效果 |
| 背景滤镜 | backdropFilter() |
更精细的模糊控制 |
| 扩展安全区 | expandSafeArea() |
内容延伸至非安全区 |
4.2 沉浸光感最佳实践
- 光效层次设计:背景光晕→内容层→玻璃拟态组件的三层架构
- 颜色管理:提取内容主色调动态调整光效颜色,保持视觉统一
- 性能优化 :使用
animation的iterations: -1创建循环动画时,注意在页面不可见时暂停 - 无障碍支持:确保在开启高对比度模式时,玻璃拟态效果自动降级为纯色背景
五、调试与测试建议
- 真机调试:玻璃拟态效果在模拟器上可能显示异常,建议在支持HarmonyOS 6的真机上测试
- 多设备适配:测试不同屏幕尺寸(手机/平板)下的悬浮导航位置
- 光效强度调节:提供用户设置入口,允许调节沉浸光效强度以适应不同环境光
六、结语
HarmonyOS 6的悬浮导航与沉浸光感特性为开发者提供了构建现代化、沉浸式UI的强大工具。通过本文的实战案例,我们展示了如何:
- 利用
setWindowLayoutFullScreen和expandSafeArea实现真正的全屏沉浸体验 - 使用
backgroundBlurStyle和backdropFilter创建玻璃拟态视觉效果 - 构建智能避让安全区的悬浮导航组件
- 实现随内容变化的动态沉浸光效
这些技术不仅提升了应用的视觉品质,更代表了下一代操作系统UI设计的演进方向。期待开发者们在HarmonyOS 6的生态中创造出更多令人惊艳的应用体验!
参考资源:
- Huawei Central - HarmonyOS 6 Glass UI Effects
- OpenHarmony 6.0 Release Notes - ArkUI Enhancements
转载自:https://blog.csdn.net/u014727709/article/details/160226304
欢迎 👍点赞✍评论⭐收藏,欢迎指正