HarmonyOS 6实战:用悬浮导航和沉浸光感做AI出行助手
HarmonyOS 6实战:用悬浮导航和沉浸光感做AI出行助手
HarmonyOS 6(API 23)带来了两个值得关注的新能力:悬浮导航和沉浸光感。它们不只是视觉上的升级,更给出行类应用提供了新的交互思路。我们尝试用这些特性做了一个叫“光语智行”的AI出行助手,把智能体的状态变化变成看得见的光效,同时用悬浮导航节省屏幕空间。

悬浮导航在出行场景中的实际价值
传统出行App底部通常有个固定Tab栏,占地方不说,还容易遮挡地图内容。HarmonyOS 6的悬浮导航解决了这个问题:
- 不抢地图空间:导航栏浮在内容上,地图能完整显示
- 毛玻璃融合:背景模糊效果让导航和地图自然衔接
- 自动调节透明度:滑动地图时导航变透明,减少干扰
- MiniBar扩展:右边还能加个语音入口或进度条
我们在真机上测试发现,这种设计在小屏手机上尤其有用——地图可视区域多了差不多10%。
沉浸光感不只是装饰,而是状态语言
很多人以为光效就是炫技,但我们把它变成了智能体的“表情”。当AI在不同阶段工作时,界面会发出对应颜色和节奏的光:
- 待机时:柔和蓝白光,3秒一次缓慢呼吸
- 听你说话:淡紫色,1.5秒脉冲,表示正在理解
- 算路线:琥珀色快闪,1秒一次,全力计算中
- 出方案:青绿色高频闪烁,800毫秒周期
- 完成任务:翠绿色确认闪光
- 出问题:橙红色急促警示
用户反馈说,这种设计让他们感觉AI真的在“思考”,而不是冷冰冰地返回结果。
窗口沉浸配置的关键细节
要实现真正的全屏光效,得先搞定窗口设置。核心是这几步:
// EntryAbility.ets
private async setupImmersiveWindow(windowStage: window.WindowStage): Promise<void> {
const mainWindow = windowStage.getMainWindowSync();
// 内容延伸到状态栏和导航栏区域
await mainWindow.setWindowLayoutFullScreen(true);
// 背景透明,让光效能透出来
await mainWindow.setWindowBackgroundColor('#00000000');
// 系统栏也设成透明
await mainWindow.setWindowSystemBarProperties({
statusBarColor: '#00000000',
navigationBarColor: '#00000000',
statusBarContentColor: '#FFFFFF',
navigationBarContentColor: '#FFFFFF'
});
// 启用安全区避让(HarmonyOS 6新增)
await mainWindow.setWindowAvoidAreaOption({
type: window.AvoidAreaType.TYPE_SYSTEM,
enabled: true
});
}这里最关键的是 setWindowAvoidAreaOption,它能自动避开刘海屏或挖孔区域。之前版本需要手动计算安全区高度,现在系统直接处理了。

智能体光效系统的实现逻辑

我们用一个控制器类管理所有光效状态:

// AgentLightEffect.ets
export enum AgentState {
IDLE, UNDERSTANDING, PLANNING, GENERATING, COMPLETED, WARNING
}
@Observed
export class AgentLightController {
@Track currentState: AgentState = AgentState.IDLE;
private stateLightMap: Map<AgentState, LightConfig> = new Map([
[AgentState.IDLE, { primaryColor: '#E8F4FD', pulseDuration: 3000, ... }],
[AgentState.UNDERSTANDING, { primaryColor: '#E0D4F7', pulseDuration: 1500, ... }],
// 其他状态配置...
]);
setState(state: AgentState): void {
this.currentState = state;
this.startPulseAnimation(); // 启动对应动画
}
}UI组件监听这个控制器,自动更新颜色和动画参数。双层光晕设计(外层大范围模糊+内层核心光)让效果更有层次,不会糊成一片。
悬浮导航的完整实现
导航栏本身是个带毛玻璃效果的容器,里面包含出行模式页签和MiniBar:
// AgentFloatNavigation.ets
build() {
Stack({ alignContent: Alignment.Bottom }) {
// 内容区域
Column() { this.contentBuilder() }
.padding({ bottom: this.bottomAvoidHeight + 90 })
// 悬浮导航容器
Column() {
// 毛玻璃背景
Column()
.backgroundBlurStyle(BlurStyle.REGULAR)
.backdropFilter($r('sys.blur.20'))
// 出行模式页签
Row() {
ForEach(this.travelModes, (item, index) => {
Column() {
Image(item.icon).fillColor(this.currentIndex === index ? item.color : '#888888')
Text(item.label).fontColor(this.currentIndex === index ? item.color : '#AAAAAA')
// 选中时的光晕指示器
if (this.currentIndex === index) {
Column()
.backgroundColor(item.color + '33')
.blur(8)
}
}.onClick(() => {
this.currentIndex = index;
this.lightController.setState(AgentState.PLANNING);
})
})
}
// MiniBar语音入口
Column() {
Image($r('app.media.ic_agent_avatar'))
.border({ color: this.lightController.getCurrentConfig().secondaryColor })
// 状态指示点
Column()
.backgroundColor(
this.lightController.currentState === AgentState.IDLE ? '#4CAF50' :
this.lightController.currentState === AgentState.WARNING ? '#FF5722' : '#FFC107'
)
}.onClick(() => {
this.lightController.setState(AgentState.UNDERSTANDING);
})
}
.gesture(LongPressGesture({ duration: 600 }).onAction(() => {
this.isExpanded = !this.isExpanded; // 长按展开透明度调节
}))
}
}长按导航栏还能展开透明度调节滑块,用户可以根据环境光调整毛玻璃强度。这个细节在强光下特别实用。
行程卡片的玻璃拟态设计
行程详情卡片用了更厚的模糊效果(BlurStyle.THICK),顶部还有个根据路况变色的光条:
- 畅通:绿色光条+绿色阴影
- 缓行:黄色光条
- 拥堵:红色光条
// TripCard.ets
build() {
Stack() {
// 厚毛玻璃背景
Column()
.backgroundBlurStyle(BlurStyle.THICK)
.backdropFilter($r('sys.blur.40'))
// 路况光效条
Column()
.backgroundColor(this.trafficColorMap.get(this.tripInfo.trafficStatus) || '#4CAF50')
.shadow({
color: (this.trafficColorMap.get(this.tripInfo.trafficStatus) || '#4CAF50') + '66'
})
// 卡片内容...
}
}实测发现,backdropFilter($r('sys.blur.40')) 比单纯用 backgroundBlurStyle 效果更细腻,但要注意性能——在低端机上可能需要降级。
语音交互页面的沉浸感营造
全屏语音页面做了三件事来增强沉浸感:
- 深色背景:用
#0A0A1A减少视觉干扰 - 动态环境光晕:大范围模糊光随状态变化
- 状态可视化:处理过程中显示光效+文字提示
// VoiceChatPage.ets
build() {
Stack() {
// 深色背景
Column().backgroundColor('#0A0A1A')
// 环境光晕
Column()
.backgroundColor(this.lightController.getCurrentConfig().primaryColor)
.blur(150)
.opacity(0.4)
.position({ x: '50%', y: '30%' })
.animation({ /* 呼吸动画 */ })
// 对话内容...
}
.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
}.expandSafeArea 让内容真正延伸到屏幕边缘,配合状态栏白色文字,整体感觉更开阔。
主页面集成与数据流
最后把所有组件串起来:
// Index.ets
build() {
AgentFloatNavigation({
lightController: this.lightController,
contentBuilder: this.MapContentBuilder.bind(this) // 注入地图内容
})
}
@Builder
MapContentBuilder(): void {
Stack() {
// 模拟地图
Column().backgroundColor('#1A1A2E')
// 路线光效轨迹
Column()
.backgroundColor('#4CAF50')
.blur(8)
.shadow({ color: '#4CAF5066' })
// 行程卡片
TripCard({ tripInfo: this.tripInfo, lightController: this.lightController })
.position({ y: 380 })
// 语音悬浮按钮
Stack() {
Column().backgroundColor(this.lightController.getCurrentConfig().secondaryColor).blur(30)
Image($r('app.media.ic_mic'))
}.onClick(() => router.pushUrl({ url: 'pages/VoiceChatPage' }))
}
}这里用 @Builder 参数把地图内容注入悬浮导航组件,避免了父子组件的强耦合。
调试时踩过的坑
- 毛玻璃效果在模拟器上失真:必须用真机测试,尤其是不同厂商的OLED屏表现差异大
- 安全区高度获取时机:要在
aboutToAppear里调用getWindowAvoidArea,太早会拿不到值 - 光效性能问题:循环动画(
iterations: -1)在页面不可见时要手动暂停,否则耗电 - 低版本兼容:API 22以下设备没有
barFloatingStyle,得回退到普通Tabs
总结
HarmonyOS 6的这两个新特性确实改变了出行App的设计思路:
- 悬浮导航让地图空间更完整
- 沉浸光感把AI状态变成可感知的视觉语言
- 玻璃拟态组件与背景自然融合
最重要的是,这些不是孤立的功能,组合起来才能产生1+1>2的效果。比如悬浮导航的MiniBar点击后唤起语音页面,光效从导航栏延续到全屏环境光,整个体验是连贯的。
未来如果系统能开放更多光效控制权限(比如调节光晕扩散速度),交互可能性还会更大。不过目前这套方案已经能在支持HarmonyOS 6的设备上跑起来了,核心代码量其实不大,关键在于把状态和视觉元素做精准映射。