OpenHarmony 英语学习 App 实战:ArkUI 卡片式学习首页与响应式布局设计
OpenHarmony 英语学习 App 实战:ArkUI 卡片式学习首页与响应式布局设计
摘要
学习类 App 的首页,不应该只是功能入口的堆叠。一个好的首页应该能告诉用户:今天学什么、当前进度怎样、下一步从哪里开始。📚✨
本文以我的 OpenHarmony/HarmonyOS 英语学习项目「英语视界 YingYu」为例,分享如何使用 ArkTS + ArkUI 设计一个卡片式学习首页。文章会结合项目中的 HomeContent.ets,讲解首页的数据加载、每日推荐、快捷入口、年级切换、响应式适配和入场动画。
一、首页设计目标
「英语视界」包含词汇学习、听力练习、每日一句、趣味英语、语法专题、短语学习、复习中心、自定义生词本等模块。如果首页只是把这些入口全部摆出来,用户会觉得复杂。
所以首页设计目标是:
- 第一屏展示用户当前学习状态;
- 每天给出一个自然推荐内容;
- 高频入口横向排列,方便快速进入;
- 手机和平板共用一套组件;
- 用轻量动画降低页面进入的生硬感。
项目首页对应文件是:
entry/src/main/ets/pages/HomeContent.ets
二、首页状态设计
首页中需要维护多个状态:每日一句、当前年级、学习统计、趣味英语推荐、听力推荐、设备类型等。
@State dailySlides: DailySentence[] = []
@State recommendSwiperIndex: number = 0
@State gradeName: string = ''
@State gradeLevel: number = 3
@State showGradePicker: boolean = false
@State totalWords: number = 0
@State consecutiveDays: number = 0
@State achievementsCount: number = 0
@State homeEnterOpacity: number = 0
@State homeEnterY: number = 20
@State dailyFunItem: FunEnglishItem | null = null
@State dailyListening: ListeningItem | null = null
@State isTabletDevice: boolean = false
这些状态可以分为三类:
- 内容状态:
dailySlides、dailyFunItem、dailyListening; - 用户状态:
gradeLevel、totalWords、consecutiveDays; - UI 状态:
showGradePicker、homeEnterOpacity、homeEnterY、isTabletDevice。
状态拆得清楚后,页面构建会更稳定。
三、aboutToAppear:进入页面时加载数据
首页在 aboutToAppear() 中加载数据,并执行入场动画。
aboutToAppear() {
this.loadData()
this.homeEnterOpacity = 0
this.homeEnterY = 20
this.isTabletDevice = isTablet()
animateTo({
duration: 520,
curve: Curve.EaseOut
}, () => {
this.homeEnterOpacity = 1
this.homeEnterY = 0
})
}
这里的动画逻辑很简单:页面从透明、下移 20 的状态过渡到正常位置。
.opacity(this.homeEnterOpacity)
.translate({ y: this.homeEnterY })
学习类 App 不适合很夸张的动效,这种轻微上浮的入场动画刚好能提升质感。
四、首页数据加载:把推荐内容和用户状态组合起来
loadData() 是首页的数据核心。它负责加载每日推荐、用户设置、学习统计、趣味英语和听力内容。
loadData() {
try {
this.dailySlides = getDailyRecommendSentences(this.recommendSlideCount)
this.recommendSwiperIndex = 0
const settings = getUserSettings()
this.gradeLevel = settings.gradeLevel
const gradeInfo = gradeInfoList.find((g: GradeInfo) => g.level === settings.gradeLevel)
this.gradeName = gradeInfo ? gradeInfo.name : '小学三年级'
const stats = getStatistics()
this.totalWords = stats.totalWords
this.consecutiveDays = stats.consecutiveDays
this.achievementsCount = stats.achievementsCount
this.dailyFunItem = getRandomFunEnglishItem()
} catch (e) {
console.error('Home loadData error:', JSON.stringify(e))
}
}
这里有一个很重要的思路:首页不直接计算所有数据,而是调用工具函数获取结果。
例如:
getUserSettings()获取用户年级和目标;getStatistics()获取学习统计;getDailyRecommendSentences()获取每日一句;getRandomFunEnglishItem()获取趣味英语推荐。
这样页面层就不会变成业务逻辑的大杂烩。
五、根据年级推荐听力难度
项目中还根据用户年级自动选择听力难度:
const settings2 = getUserSettings()
const gradeLvl = settings2.gradeLevel
let diffLevel = 1
if (gradeLvl <= 3) diffLevel = 1
else if (gradeLvl <= 6) diffLevel = 2
else if (gradeLvl <= 9) diffLevel = 3
else diffLevel = 4
const listenItems = getListeningItemsByDifficulty(diffLevel)
这个逻辑很适合教育类产品:
- 小学低年级:简单句;
- 小学高年级:短对话;
- 初中:中等材料;
- 高中:更复杂文本。
推荐内容不需要一开始就用复杂 AI,先用规则就能提升匹配度。
六、页面结构:多个 Builder 组成首页
首页主体结构很清晰:
build() {
Scroll() {
Column() {
this.WelcomeSection()
this.DailyRecommendCard()
this.QuickAccessSection()
this.FunEnglishPickSection()
this.ListeningRecommendSection()
this.FeatureGrid()
this.StatisticsCard()
}
.width('100%')
.padding({
left: getPagePadding(),
right: getPagePadding(),
top: 12,
bottom: 28
})
.opacity(this.homeEnterOpacity)
.translate({ y: this.homeEnterY })
}
.width('100%')
.height('100%')
.edgeEffect(EdgeEffect.Spring)
}
每个区域都拆成独立 Builder:
WelcomeSection():欢迎区和年级选择;DailyRecommendCard():每日一句;QuickAccessSection():快捷入口;FunEnglishPickSection():趣味英语推荐;ListeningRecommendSection():听力推荐;FeatureGrid():功能网格;StatisticsCard():学习统计。
这种写法比把所有 UI 都堆在 build() 中更好维护。
七、快捷入口:横向滚动降低首页拥挤感
首页功能很多,如果全部放成网格,会占用太多垂直空间。项目使用横向滚动展示快捷入口:
@Builder
QuickAccessScroll() {
Scroll() {
Row() {
this.QuickAccessTile('每日任务', '任务中心', $r('sys.symbol.calendar'), $r('app.color.listening_solid'), () => router.pushUrl({ url: 'pages/DailyTask' }))
this.QuickAccessTile('复习中心', '艾宾浩斯', $r('sys.symbol.arrow_2_circlepath'), $r('app.color.icon_tag_grade'), () => router.pushUrl({ url: 'pages/ReviewCenter' }))
this.QuickAccessTile('学习目标', '设定目标', $r('sys.symbol.book'), $r('app.color.icon_tag_goal'), () => router.pushUrl({ url: 'pages/LearningGoals' }))
this.QuickAccessTile('学习日历', '打卡记录', $r('sys.symbol.calendar'), $r('app.color.primary_color'), () => router.pushUrl({ url: 'pages/LearningCalendar' }))
}
.alignItems(VerticalAlign.Center)
}
.width('100%')
.scrollable(ScrollDirection.Horizontal)
.scrollBar(BarState.Off)
.edgeEffect(EdgeEffect.Spring)
}
横向入口适合放高频功能:
- 每日任务;
- 复习中心;
- 学习目标;
- 学习日历;
- 自定义生词;
- 语法学习;
- 短语学习。
用户不需要一次看到所有内容,但可以很快滑动找到入口。
八、年级切换:首页直接影响推荐策略
首页的年级选择不是装饰,而是会影响推荐内容和学习难度。
private applyGradeLevel(level: number): void {
const prev = getUserSettings()
const next: UserSettings = {
gradeLevel: level,
dailyGoal: prev.dailyGoal,
notificationsEnabled: prev.notificationsEnabled,
soundEnabled: prev.soundEnabled
}
saveUserSettings(next)
const gradeInfo = gradeInfoList.find((g: GradeInfo) => g.level === level)
this.gradeName = gradeInfo ? gradeInfo.name : '小学三年级'
this.gradeLevel = level
this.showGradePicker = false
}
这段代码做了三件事:
- 保留原来的每日目标、通知和声音设置;
- 更新年级;
- 关闭选择面板并刷新显示。
对学习 App 来说,年级是非常重要的用户画像字段,应该贯穿词汇、听力、语法、推荐内容。
九、响应式布局:用工具函数统一页面间距
首页没有在每个地方手写固定边距,而是调用 getPagePadding()、getSectionGap() 等工具函数。
.padding({
left: getPagePadding(),
right: getPagePadding(),
top: 12,
bottom: 28
})
同时根据 isTabletDevice 调整字号、圆角和 padding:
Text('欢迎来到英语视界')
.fontSize(this.isTabletDevice ? 26 : 22)
.fontWeight(FontWeight.Bold)
.padding(this.isTabletDevice ? 24 : 18)
.borderRadius(this.isTabletDevice ? 24 : 18)
这样一套页面可以同时适配手机和平板,不需要维护两套首页。
十、首页设计经验总结
1. 首页要回答“下一步做什么”
学习类首页不要只展示品牌和 Banner,要把“每日任务”“复习中心”“今日推荐”放在用户最容易看到的位置。
2. 推荐内容要和用户状态相关
年级、学习进度、连续打卡天数都可以影响推荐策略。
3. 卡片式布局要克制
卡片太多会变成信息噪音。建议按优先级排序:状态卡、推荐卡、快捷入口、统计卡。
4. 动效要服务进入感
轻微透明度和位移动画就足够,不要让学习 App 像游戏大厅。
十一、小结
本文结合「英语视界 YingYu」的 HomeContent.ets,拆解了 OpenHarmony/ArkUI 卡片式首页的实现方式:
- 使用
@State管理首页内容、用户状态和 UI 状态; - 在
aboutToAppear()中加载数据并执行入场动画; - 通过
loadData()聚合每日推荐、学习统计和听力推荐; - 使用多个 Builder 拆分首页模块;
- 横向滚动展示快捷入口;
- 年级切换影响推荐策略;
- 使用响应式工具函数适配手机和平板。
一个好的学习首页,不是把功能放满,而是让用户愿意开始下一次学习。🌱

更多推荐



所有评论(0)