news 2026/6/22 15:55:38

【共创季稿事节】动图魔方技术拆解 01:HarmonyOS 6.1 沉浸光感实战:底部页签材质改造

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【共创季稿事节】动图魔方技术拆解 01:HarmonyOS 6.1 沉浸光感实战:底部页签材质改造

SEO 信息

  • **SEO 标题**:【共创季稿事节】HarmonyOS 6.1 沉浸光感实战:ArkUI 底部 Tab 毛玻璃材质改造
  • **SEO 摘要**:本文以一个 HarmonyOS NEXT / ArkTS 实战项目“动图魔方”为例,记录底部 Tab 从灰色实底改造成沉浸光感材质导航的全过程。文章覆盖 ArkUI `backgroundBlurStyle`、`BlurStyle.COMPONENT_THICK`、透明背景、径向光池、深浅色主题、模拟器验收与踩坑复盘。
  • **关键词**:HarmonyOS, ArkTS, ArkUI, 沉浸光感, 毛玻璃, BlurStyle, 底部导航, 主题切换
  • **文章封面**:建议使用 `doc/screenshots_current/gifrubik_glass_material_editor_final.jpeg` 或底部 Tab 对比拼图
  • **投稿方向**:HarmonyOS 6.1 创新特性适配实战
  • **项目环境**:HarmonyOS SDK `6.1.0(23)`,ArkTS,DevEco Studio,GIFRubiksCube 项目

这篇文章来自“动图魔方”项目的一次真实 UI 改造:底部 Tab 看起来像一块灰色实底,用户一眼就能感到“不透明、没有材质感”。本文记录我如何在 ArkUI 中把它改成更接近 HarmonyOS 6.1 沉浸光感的底部导航,并把这个过程整理成可复用的工程方法。

一、真实问题背景

“动图魔方”是一个本地优先的 GIF 创作工具,核心功能包括图片/视频/GIF 素材导入、帧处理、比例和帧率控制、GIF89a 编码、作品保存与分享。

在功能逐步补齐后,底部 Tab 成了一个很明显的视觉短板:它承担首页、作品、创建、发现、我的五个入口,但模拟器里看起来更像一个灰色胶囊浮层。尤其在编辑页内容滚动到底部时,导航栏没有透出下层内容,也没有 HarmonyOS 6.1 里“沉浸光感”强调的材质层次。

这类问题不是简单换个颜色就能解决。因为用户感知到的是三件事叠在一起:

  • 底部导航是否像一个浮在内容上方的系统材质层;
  • 页面背景是否给材质提供了足够的光感和层次;
  • 深浅色、选中态、创建按钮是否在不同页面里保持一致。

所以这次改造没有只改一个backgroundColor,而是同时处理 Tab 背景、模糊材质、页面环境光、主题切换和页面内容的关系。

二、目标与边界

这次改造的目标很明确:

1. 底部 Tab 不再是灰色实底,而是半透明材质层;

2. 导航栏要能透出下层 App 内容,而不是只模糊壁纸;

3. 浅色、深色、跟随系统三种主题都要可用;

4. 选中态、创建按钮、阴影和边框要保持稳定,不因为文字或状态变化抖动;

5. 不引入不确定 API,不用网上未经验证的“光照接口”。

边界也同样重要:

  • 当前版本优先使用标准 ArkUI 能力完成稳定落地;
  • 真正的 HDS 组件化 Tabs 或 UIDesignKit 后续可再整体替换;
  • 本次不改变 GIF 导出、素材选择、作品管理等业务链路;
  • 模拟器验收以“可见半透明材质”和“深浅色不崩”为准。

三、方案拆分

我把底部导航拆成三层来看:

层级责任对应实现
页面背景层提供环境光和底色`pageBg()` + `radialGradient()`
材质容器层负责半透明、模糊、阴影、边框`BottomNav()`
交互项层负责选中态、创建按钮和页面切换`NavItem()` + `CreateNavItem()`

最关键的一点是:如果底部容器本身使用高不透明灰色背景,即使加了backgroundBlurStyle,用户也几乎看不到模糊效果。模糊被实底盖住,自然会显得“假”。

因此最终方案是:

  • 使用 `BlurStyle.COMPONENT_THICK` 作为底部 Tab 的模糊材质;
  • 背景色只保留低透明度浅/深色调;
  • 边框使用半透明白色增强轮廓;
  • 页面根背景增加径向光池,让材质层有可感知的透光对象;
  • “我的”页加入主题切换入口,让用户能主动切换系统、浅色、深色模式。

四、关键实现

4.1 底部 Tab:从实底改成组件材质模糊

底部导航核心代码在entry/src/main/ets/pages/Index.etsBottomNav()

@Builder BottomNav() { Row() { this.NavItem('首页', 'home') this.NavItem('作品', 'works') this.CreateNavItem() this.NavItem('发现', 'discover') this.NavItem('我的', 'profile') } .height(76) .width('90%') .padding({ left: 9, right: 9, top: 9, bottom: 9 }) .margin({ bottom: 14 }) .borderRadius(28) // 毛玻璃:用 COMPONENT 材质模糊下层 App 内容; // 背景仅留极低透明度的浅色/深色调,避免盖住模糊材质。 .backgroundBlurStyle(BlurStyle.COMPONENT_THICK) .backgroundColor(this.darkPreview ? '#33242235' : '#38FFFFFF') .border({ width: 1, color: this.darkPreview ? '#40FFFFFF' : '#80FFFFFF' }) .shadow({ radius: 22, color: this.darkPreview ? '#66000000' : '#1F000000', offsetX: 0, offsetY: 8 }) }

这里有两个细节值得单独说。

第一个是BlurStyle.COMPONENT_THICK。我一开始使用过BACKGROUND_THIN,但它更偏向窗口背景/壁纸一类的模糊,放在 App 内部浮层上时,用户很难看到底部内容被模糊后的效果。改成COMPONENT_THICK后,底部 Tab 能直接作用于下层 App 内容,视觉上才更像真正浮在内容上方。

第二个是背景透明度。浅色模式下使用#38FFFFFF,深色模式下使用#33242235。这两个颜色都不是为了“铺底”,而是给材质一个非常轻的调色。这样既不会露得太空,也不会把模糊效果盖住。

4.2 页面根背景:给材质一个“可透”的环境

只有 Tab 自己半透明还不够。如果页面背景是一整块单调颜色,毛玻璃也很难有层次。因此在页面根节点上增加了径向光池:

build() { Stack({ alignContent: Alignment.Bottom }) { Column() { if (this.page === 'editor') { this.EditorPage() } else if (this.page === 'works') { this.WorksPage() } else if (this.page === 'discover') { this.DiscoverPage() } else if (this.page === 'profile') { this.ProfilePage() } else { this.HomePage() } } .width(this.contentWidth()) .height('100%') this.BottomNav() } .width('100%') .height('100%') .backgroundColor(this.pageBg()) .radialGradient(this.darkPreview ? { center: ['50%', '6%'], radius: '140%', colors: [['#2E2950', 0.0], ['#1B1929', 0.5], ['#121120', 1.0]] } : { center: ['50%', '5%'], radius: '130%', colors: [['#FFFFFF', 0.0], ['#F8F6FF', 0.45], ['#EFEAFE', 1.0]] }) }

这一步的作用不是做炫酷背景,而是让页面有一个从顶部中心扩散的环境光。底部材质层透出内容时,用户能看到背景明暗变化,导航栏才不会像一块孤立贴片。

4.3 主题切换:把“我的”页变成偏好中心

改视觉时还有一个连带问题:发现页和我的页如果都只是空状态,就会显得没有拆分意义。于是我把“我的”页定位成本地偏好、隐私和工作台,主题切换放到这里。

private async loadThemeMode(): Promise<void> { const mode = await StorageService.loadThemeMode(this.ctx()); this.themeMode = mode; this.darkPreview = mode === 'dark'; this.applyColorMode(mode); } private applyColorMode(mode: string): void { try { if (mode === 'dark') { this.ctx().getApplicationContext() .setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_DARK); } else if (mode === 'light') { this.ctx().getApplicationContext() .setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT); } else { this.ctx().getApplicationContext() .setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); } } catch (err) { } }

对应 UI 是三个分段选项:

Row({ space: 8 }) { this.ThemeChoice('跟随系统', 'system') this.ThemeChoice('浅色', 'light') this.ThemeChoice('深色', 'dark') }

这里没有把主题切换藏在设置二级页里,是因为它正好服务于本次视觉改造的验收:用户可以直接在“我的”页切换浅色、深色、跟随系统,并观察底部 Tab、页面卡片、文字颜色是否同步变化。

五、踩坑与修正

5.1 为什么加了 blur 还是像灰底

最初的问题不是没有调用模糊,而是模糊被不透明背景盖住了。比如一个接近 70% 不透明度的灰色底,再叠实色渐变,视觉结果一定更接近“灰胶囊”,而不是“玻璃”。

修正思路是反过来:先保证材质可见,再用极低透明度背景给它调色。

5.2 `BACKGROUND_THIN` 不适合这个浮层场景

BACKGROUND_THIN在某些场景下看不到明显变化,是因为它并不等价于“模糊当前组件下面的 App 内容”。底部 Tab 是 App 内部的浮层,需要的是组件层级下方内容参与模糊,因此改用COMPONENT_THICK

这也是本次最有价值的结论:做 App 内部毛玻璃时,先确认模糊对象是谁。模糊壁纸和模糊组件下层内容,是两个完全不同的视觉结果。

5.3 光感不能靠不存在的 API

调研过程中也看到过一些社区文章提到类似lighting.setLightEffect的接口,但没有在官方能力里确认到稳定可用形态。为了避免给项目引入不可靠依赖,本次没有采用这类写法,而是使用 ArkUI 标准背景、模糊、透明度、阴影组合实现。

这对工程项目很重要:视觉效果可以迭代,但底层 API 必须可靠。尤其是准备上架或参赛投稿时,文章里要能说明“为什么这么做”,而不是只贴一段不可验证代码。

六、调试与验收

本次验收主要看三组截图:

  • 改造前:底部 Tab 呈灰色实底,材质感弱;
  • 改造后浅色:底部导航能透出编辑页内容,边框和阴影轻量;
  • 改造后深色:导航栏仍有可辨识层次,选中态与创建按钮不丢失。

本项目当前可用截图位于:

  • `doc/screenshots_current/gifrubik_immersive_bottom_nav.jpeg`
  • `doc/screenshots_current/gifrubik_immersive_light_bottom_nav.jpeg`
  • `doc/screenshots_current/gifrubik_glass_material_editor_final.jpeg`
  • `doc/screenshots_current/gifrubik_profile_expanded_dark_nav.jpeg`

构建方面,项目 SDK 配置已经修正为:

{ "targetSdkVersion": "6.1.0(23)", "compatibleSdkVersion": "6.1.0(23)" }

Hvigor 构建结果为:

BUILD SUCCESSFUL

构建仍有部分警告,例如后台任务能力、弃用 API 和异常处理提示,但这些不影响本次底部导航视觉改造的编译通过。涉及系统受限能力的部分,项目中已通过能力门控和降级处理隔离。

七、工程复盘

这次改造看似只是底部 Tab 的 UI 调整,实际复盘下来有三个工程经验。

第一,材质感不是单个属性。backgroundBlurStyle、透明背景、边框、阴影、页面底色和内容层次共同决定最终观感。只加 blur,通常不够。

第二,页面功能分区会影响视觉可信度。发现页负责模板、教程和 Image2 灵感;我的页负责主题、隐私和设备能力。页面职责明确后,底部 Tab 的五个入口才不是摆设。

第三,视觉改造也要写验收条件。比如“半透明”不能只凭主观描述,需要在模拟器截图里看到下层内容参与材质效果;“深色可用”也不能只改背景色,需要检查文字、卡片、按钮和导航选中态。

八、验收清单

验收项结果说明
底部 Tab 不再使用高不透明灰底通过背景改为低透明浅/深色
App 内部内容参与模糊通过使用 `BlurStyle.COMPONENT_THICK`
页面具备环境光层次通过根节点增加 `radialGradient`
浅色主题可用通过文字、卡片、导航保持对比度
深色主题可用通过主题切换入口在“我的”页
跟随系统可用通过使用应用级 `setColorMode`
构建通过通过Hvigor 输出 `BUILD SUCCESSFUL`
未引入不可靠光照 API通过只使用标准 ArkUI 能力

九、小结

HarmonyOS 6.1 的沉浸光感,不应该被理解成“加一层半透明背景”。在真实工程里,它更像一个系统化的视觉关系:内容要在下面流动,材质要能透出层次,主题要能切换,入口职责要清楚。

对“动图魔方”来说,这次改造的价值不只是底部导航变好看了,而是让整个创作工具从“功能堆叠”往“可持续扩展的产品界面”走了一步。后续如果继续接入 HDS Tabs 或 UIDesignKit,也可以在这套页面职责和主题体系上平滑替换。

十、下一篇衔接

下一篇我会继续拆“动图魔方”的核心能力:如何在 HarmonyOS 6.1 中使用 Media Kit 从视频抽帧,并把帧序列送入 GIF89a 编码链路。那一篇会更偏底层:AVImageGeneratorPixelMap、帧率限制、尺寸压缩、LZW 编码和导出进度。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/22 15:45:42

Kinetis SDK时钟管理器:从寄存器操作到抽象管理的演进与实践

1. Kinetis SDK时钟管理器&#xff1a;从寄存器操作到抽象管理的演进在嵌入式开发领域&#xff0c;尤其是基于ARM Cortex-M内核的MCU项目中&#xff0c;时钟配置往往是项目启动阶段的第一道“拦路虎”。我记得自己早期接触Freescale&#xff08;现NXP&#xff09;的Kinetis系列…

作者头像 李华
网站建设 2026/6/22 15:28:19

5分钟打造专业级音乐播放器:foobar2000终极美化指南

5分钟打造专业级音乐播放器&#xff1a;foobar2000终极美化指南 【免费下载链接】foobox-cn DUI 配置 for foobar2000 项目地址: https://gitcode.com/GitHub_Trending/fo/foobox-cn 还在为foobar2000单调的默认界面感到乏味吗&#xff1f;想要将你的音乐播放器打造成既…

作者头像 李华
网站建设 2026/6/22 15:24:20

嵌入式DSP开发利器:LSP APU向量点积指令深度解析与应用

1. 轻量级信号处理APU与向量点积运算概述在嵌入式数字信号处理&#xff08;DSP&#xff09;和实时控制系统的开发中&#xff0c;我们经常面临一个核心矛盾&#xff1a;算法对计算吞吐量的高要求与嵌入式平台有限的功耗、面积预算之间的冲突。尤其是在音频编解码、图像滤波、通信…

作者头像 李华
网站建设 2026/6/22 15:13:04

从CVE-2025-24813漏洞防御实战,拆解企业级立体化安全防护体系构建

1. 项目概述&#xff1a;从一次真实的告警说起那天下午&#xff0c;监控大屏上一个平时几乎不动的指标突然开始剧烈跳动——来自边界防火墙的异常连接数告警。作为运维负责人&#xff0c;我的第一反应是检查是否有新的业务上线或者遭到了扫描。但很快&#xff0c;来自不同业务区…

作者头像 李华