【OpenHarmony/HarmonyOs 】数学视界实战:悬浮导航栏、沉浸光感与全新交互体验
【OpenHarmony/HarmonyOs 】数学视界实战:悬浮导航栏、沉浸光感与全新交互体验
项目类型:OpenHarmony / HarmonyOS ArkTS 数学学习应用
项目名称:数学视界
关键词:ArkUI、Tabs、沉浸式视觉、深色模式、底部导航、点击动效、响应式布局 ✨
一、为什么要做“轻沉浸”的数学学习体验?
数学类应用很容易做成“工具集合”:计算器、公式表、单位换算、题库练习各自独立,页面之间缺少情绪连接。我的这个项目希望让用户打开应用时,不只是看到一堆功能按钮,而是进入一个有节奏、有反馈、有学习目标的空间。
所以在 UI 设计上,我重点做了三件事:
- 🌈 用暖色光感做首页视觉入口,让学习氛围更轻松;
- 🧭 用底部导航承载高频页面:首页、挑战、成就、收藏、我的;
- 👆 给按钮、卡片、弹窗都加上统一点击反馈,让每一次操作都有回应。
最终效果上,应用并不是简单堆 ArkUI 组件,而是围绕“今日目标 -> 功能探索 -> 学习数据 -> 成就反馈”形成一个完整体验闭环。
二、项目首页结构:Tabs 承载五大核心场景
项目的主入口在 entry/src/main/ets/pages/Index.ets,首页没有使用多个独立 Ability,而是通过 Tabs 把几个主要场景组织到同一个主页面里。
核心结构如下:
Tabs({ barPosition: BarPosition.End, controller: this.tabController }) {
TabContent() {
this.buildHomePage()
}
.tabBar(this.buildBottomTab(0, '🏠', '首页'))
TabContent() {
this.buildChallengeTab()
}
.tabBar(this.buildBottomTab(1, '🎯', '挑战'))
TabContent() {
this.buildAchievementTab()
}
.tabBar(this.buildBottomTab(2, '🏆', '成就'))
TabContent() {
this.buildFavoritesTab()
}
.tabBar(this.buildBottomTab(3, '💖', '收藏'))
TabContent() {
MyPage()
}
.tabBar(this.buildBottomTab(4, '👤', '我的'))
}
.barHeight(56)
.barBackgroundColor(this.getColor('#FFFDF7', '#1C1C1E'))
.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.BOTTOM])
这里有几个细节很关键:
barPosition: BarPosition.End:把导航固定在底部,更符合移动端单手操作习惯。TabsController:为后续主动切换 Tab 留出扩展空间。expandSafeArea:处理底部安全区域,让导航不会被系统手势区域遮挡。- 自定义
tabBar:不用系统默认样式,而是自己绘制图标、文字、角标。
三、底部导航栏:不只是切换页面,还要承担状态表达
数学视界的底部导航有一个小设计:收藏 Tab 会显示收藏数量角标。这样用户不用进入收藏页,也能知道自己积累了多少内容。
@Builder
buildBottomTab(index: number, icon: string, title: string) {
Column({ space: 2 }) {
Stack({ alignContent: Alignment.Center }) {
Text(icon)
.fontSize(24)
if (index === 3 && AppState.favorites.length > 0) {
Text(AppState.favorites.length > 99 ? '99+' : AppState.favorites.length.toString())
.fontSize(9)
.fontColor('#FFFFFF')
.backgroundColor(this.isDarkMode ? '#FF7A8A' : '#FF6B9D')
.borderRadius(10)
.padding({ left: 3, right: 3, top: 1, bottom: 1 })
.offset({ x: 14, y: -10 })
}
}
Text(title)
.fontSize(11)
.fontWeight(this.currentIndex === index ? FontWeight.Bold : FontWeight.Normal)
.fontColor(this.currentIndex === index ? getThemeColors().primary : this.getColor('#AAAAAA', '#666666'))
.textAlign(TextAlign.Center)
}
}
这个写法的好处是:
- 当前选中态通过字重和颜色表达,用户不会迷路;
- 收藏数量直接关联
AppState.favorites.length,数据变化会反映到 UI; - 深色模式下角标颜色也会调整,不会出现浅色主题好看、深色主题刺眼的问题。
四、沉浸光感:从首页头图到进度卡片
首页最醒目的区域是顶部标题和今日进度。它们都使用了比较明亮的暖粉色,形成统一的品牌感。
Text('🌟 数学视界')
.fontSize(this.isLargeScreen ? 26 : 22)
.fontWeight(FontWeight.Bold)
.fontColor('#FFFFFF')
Text('探索数学的奇妙世界')
.fontSize(this.isLargeScreen ? 14 : 12)
.fontColor('rgba(255,255,255,0.85)')
进度卡片则把“今日目标”直接视觉化:
Column()
.width(Math.min(AppState.studyData.todayCount / AppState.studyData.dailyGoal * 100, 100) + '%')
.height('100%')
.backgroundColor('#FFFFFF')
.borderRadius(10)
这里我没有把学习数据藏在“我的”页面里,而是放在首页首屏。原因很简单:学习类产品最重要的是持续激励,用户一打开就应该知道“今天还差多少”。
页面文案也做了轻量反馈:
Text(
AppState.studyData.todayCount >= AppState.studyData.dailyGoal
? '🎉 太棒了!今日目标达成!'
: '💪 再完成 ' + Math.max(AppState.studyData.dailyGoal - AppState.studyData.todayCount, 0) + ' 次即可达成今日目标!'
)
这类微文案虽然代码很短,但对学习应用的体验很重要。它让进度条不只是一个数字,而是一个“被鼓励”的瞬间。
五、统一点击动效:让交互有手感
项目中很多按钮、卡片、弹窗关闭按钮都用了同一套点击反馈。核心思路是:点击时记录当前元素的 id,短时间内让该元素缩小和降低透明度。
pulseAnim(id: string): void {
this.animId = id
if (this.animTimer >= 0) clearTimeout(this.animTimer)
this.animTimer = setTimeout((): void => {
this.animId = ''
}, 200) as number
}
animScale(id: string): number {
return this.animId === id ? AnimScale.PRESSED : 1
}
animAlpha(id: string): number {
return this.animId === id ? AnimAlpha.PRESSED : 1
}
在功能卡片上使用:
.scale({ x: this.animScale('mod_' + title), y: this.animScale('mod_' + title) })
.opacity(this.animAlpha('mod_' + title))
.animation({ duration: AnimDuration.NORMAL, curve: Curve.EaseOut })
.onClick(() => {
this.pulseAnim('mod_' + title)
action()
})
体验上会变成这样:
- 用户点卡片时,卡片轻微下压;
- 点击反馈在 200ms 左右结束;
- 动画不会抢戏,但会让页面更“活”。
我把这类动效抽到了 AnimationUtils.ets,统一维护时长、缩放值和透明度:
export const AnimDuration = {
FAST: 100,
NORMAL: 150,
SLOW: 300,
VERY_SLOW: 500,
}
export const AnimScale = {
PRESSED: 0.93,
SMALL: 0.95,
LARGE: 1.05,
}
export const AnimAlpha = {
PRESSED: 0.82,
DISABLED: 0.5,
}
这样后续新增页面时,不需要每个页面都重新想一套动画参数,整套应用的手感会保持一致。
六、深色模式:不是简单反色,而是主题系统
项目中有一个统一的 ThemeManager,用于管理浅色主题、深色主题、图标背景映射和响应式工具。
export const LightTheme: ThemeColors = {
primary: '#FF7A8A',
background: '#FFF8F0',
surface: '#FFFFFF',
textPrimary: '#2C3E50',
tabBarBackground: '#FFFDF7',
}
export const DarkTheme: ThemeColors = {
primary: '#FF7A8A',
background: '#000000',
surface: '#1C1C1E',
textPrimary: '#F2F2F7',
tabBarBackground: '#1C1C1E',
}
深色模式最容易踩坑的地方是图标背景。浅色模式下很多柔和色块很舒服,但放到黑色背景上会显得发灰或发脏。因此项目里单独维护了图标背景映射:
export function getIconBgColor(lightColor: string, isDark: boolean): string {
if (!isDark) return lightColor
const mapping = IconBgColorMap[lightColor]
if (mapping) return mapping.dark
return adjustColorForDark(lightColor)
}
这样首页、我的页面、挑战页都可以复用:
getIconBg(bgColor: string): string {
return getIconBgColor(bgColor, this.isDarkMode)
}
七、状态栏同步:让系统区域也融入视觉
在 EntryAbility.ets 中,应用会读取系统配置并更新主题状态,同时设置状态栏颜色。
onConfigurationUpdate(newConfig: Configuration): void {
ThemeManager.getInstance().applyColorMode(newConfig.colorMode)
this.applyStatusBar()
}
private applyStatusBar(): void {
if (this.mainWindow === null) return
const isDark = ThemeManager.getInstance().isDark()
this.mainWindow.setWindowSystemBarProperties({
statusBarColor: isDark ? '#1C1C1E' : '#FF9A8B',
statusBarContentColor: '#FFFFFF'
})
}
这一步会让应用不只是内容区变色,连状态栏也与页面主色协调起来。对于“沉浸光感”来说,这种细节非常重要。
八、响应式适配:手机和平板都要能用
项目在 ThemeManager.ets 中封装了 ResponsiveUtils:
export class ResponsiveUtils {
private static readonly BASE_WIDTH = 375
static getScreenWidth(): number {
return getScreenSize().width
}
static isLargeScreen(): boolean {
return getScreenSize().width >= 600
}
static getGridColumns(): number {
return ResponsiveUtils.isLargeScreen() ? 4 : 2
}
}
首页里根据屏幕宽度调整字号、间距和内容宽度:
get isLargeScreen() {
return this.screenWidth >= 600
}
这让应用在手机上保持紧凑,在平板上则不会显得内容过小。
九、实现总结
这篇文章对应的主题是“悬浮导航栏、沉浸光感、全新视觉与交互体验”。在数学视界项目里,我主要通过以下方式实现:
- 🧭 使用
Tabs + 自定义 tabBar构建底部导航; - 🌈 使用暖色头部、进度卡片和轻渐变营造学习氛围;
- 👆 抽象
AnimDuration / AnimScale / AnimAlpha,统一点击动效; - 🌙 使用
ThemeManager管理深色模式和图标背景映射; - 📱 使用
ResponsiveUtils处理手机和平板适配; - 🧩 把首页、挑战、成就、收藏、我的组成完整学习闭环。
如果你也在做 OpenHarmony / HarmonyOS 应用,不建议一开始就追求复杂动画。先把导航、主题、点击反馈、状态栏、安全区域这些基础体验做好,应用的完成度会立刻提升一大截。🚀

更多推荐


所有评论(0)