flutter_for_openharmony手语学习app实战+闪卡练习实现
本文介绍了一个手语闪卡应用的实现方案。该应用采用正面显示词汇、反面展示手语动作的设计,支持点击翻转和左右滑动切换卡片。代码结构包含状态管理(_currentIndex和_showAnswer)、卡片数据准备(包含8个基础手语词汇)、页面布局(AppBar显示进度、手势交互区域)以及卡片正反面内容展示。通过AnimatedSwitcher实现300毫秒的平滑过渡动画,提升用户体验。该方案适用于语言学

闪卡是一种高效的记忆方式,正面显示词汇,点击翻转显示手语动作说明。用户可以左右滑动切换卡片,标记掌握程度来强化记忆效果。
状态变量定义
闪卡需要追踪当前索引和翻转状态:
class FlashcardScreen extends StatefulWidget {
const FlashcardScreen({super.key});
State<FlashcardScreen> createState() => _FlashcardScreenState();
}
class _FlashcardScreenState extends State<FlashcardScreen> {
int _currentIndex = 0;
bool _showAnswer = false;
_currentIndex是当前卡片索引,_showAnswer控制是否显示答案面。这两个状态会随用户操作频繁变化。
闪卡数据准备
准备一组手语词汇卡片:
final List<Map<String, String>> _cards = [
{
'word': '你好',
'description': '右手握拳,拇指伸出,从额头向前挥动'
},
{
'word': '谢谢',
'description': '右手平伸,手心向上,从下巴处向前推出'
},
{
'word': '对不起',
'description': '右手握拳放在胸前,顺时针画圈'
},
{
'word': '再见',
'description': '手掌向外,左右摆动'
},
每张卡片包含词汇和动作描述,实际项目中还可以加入图片或视频链接。
{
'word': '我爱你',
'description': '同时伸出拇指、食指和小指'
},
{
'word': '帮助',
'description': '一只手托住另一只手的拳头向上推'
},
{
'word': '吃饭',
'description': '手指并拢,做往嘴里送食物的动作'
},
{
'word': '喝水',
'description': '手做握杯状,向嘴边倾斜'
},
];
涵盖基础问候、情感表达、日常用语等多个类别的词汇。
页面整体结构
AppBar显示进度,body包含卡片和控制按钮:
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('闪卡练习'),
actions: [
Center(
child: Padding(
padding: EdgeInsets.only(right: 16.w),
child: Text(
'${_currentIndex + 1}/${_cards.length}',
style: TextStyle(fontSize: 16.sp),
),
),
),
],
),
AppBar右侧显示当前是第几张卡片,让用户了解练习进度。
手势交互区域
点击翻转,滑动切换:
body: Column(
children: [
Expanded(
child: GestureDetector(
onTap: () => setState(() => _showAnswer = !_showAnswer),
onHorizontalDragEnd: (details) {
if (details.primaryVelocity! < 0) {
_nextCard();
} else if (details.primaryVelocity! > 0) {
_previousCard();
}
},
onTap切换正反面,onHorizontalDragEnd检测滑动方向。primaryVelocity小于0是左滑下一张,大于0是右滑上一张。
child: Container(
margin: EdgeInsets.all(20.w),
child: AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
child: _buildCard(),
),
),
),
),
_buildControls(),
SizedBox(height: 20.h),
],
),
);
}
AnimatedSwitcher在卡片切换时自动添加过渡动画,300毫秒的时长比较自然流畅。
卡片组件构建
根据状态显示正面或反面:
Widget _buildCard() {
final card = _cards[_currentIndex];
return Card(
key: ValueKey('$_currentIndex-$_showAnswer'),
elevation: 8,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.r),
),
child: Container(
width: double.infinity,
padding: EdgeInsets.all(32.w),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (!_showAnswer) ...[
key包含索引和状态,确保AnimatedSwitcher能正确识别变化触发动画。elevation: 8给卡片添加阴影效果。
卡片正面内容
显示词汇和提示:
Icon(
Icons.sign_language,
size: 100.sp,
color: const Color(0xFF00897B),
),
SizedBox(height: 32.h),
Text(
card['word']!,
style: TextStyle(
fontSize: 48.sp,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 16.h),
Text(
'点击查看手语动作',
style: TextStyle(
fontSize: 14.sp,
color: Colors.grey
),
),
]
正面显示大号词汇和手语图标,底部提示用户点击查看答案。大字体设计让词汇更醒目。
卡片反面内容
显示动作描述:
else ...[
Container(
width: 150.w,
height: 150.w,
decoration: BoxDecoration(
color: const Color(0xFF00897B).withOpacity(0.1),
borderRadius: BorderRadius.circular(75.r),
),
child: Icon(
Icons.sign_language,
size: 80.sp,
color: const Color(0xFF00897B),
),
),
反面图标放在圆形背景中,视觉上更柔和。
SizedBox(height: 32.h),
Text(
card['word']!,
style: TextStyle(
fontSize: 32.sp,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 16.h),
Container(
padding: EdgeInsets.all(16.w),
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(12.r),
),
child: Text(
card['description']!,
style: TextStyle(fontSize: 16.sp, height: 1.5),
textAlign: TextAlign.center,
),
),
],
],
),
),
);
}
词汇字号略小,重点是下方的动作描述。灰色背景让描述区域更突出。height: 1.5增加行高提升可读性。
控制区域构建
底部显示进度指示器和操作按钮:
Widget _buildControls() {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 20.w),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(_cards.length, (index) {
return Container(
width: 8.w,
height: 8.w,
margin: EdgeInsets.symmetric(horizontal: 4.w),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: index == _currentIndex
? const Color(0xFF00897B)
: Colors.grey[300],
),
);
}),
),
小圆点指示器,当前卡片对应的圆点用主题色高亮。List.generate根据卡片数量生成圆点。
掌握程度按钮
两个按钮标记掌握情况:
SizedBox(height: 20.h),
Row(
children: [
Expanded(
child: ElevatedButton.icon(
onPressed: () => _markCard(false),
icon: const Icon(Icons.close, color: Colors.white),
label: const Text(
'不熟悉',
style: TextStyle(color: Colors.white)
),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.red[400],
padding: EdgeInsets.symmetric(vertical: 12.h),
),
),
),
红色"不熟悉"按钮,点击后标记这张卡片需要继续练习。
SizedBox(width: 12.w),
Expanded(
child: ElevatedButton.icon(
onPressed: () => _markCard(true),
icon: const Icon(Icons.check, color: Colors.white),
label: const Text(
'已掌握',
style: TextStyle(color: Colors.white)
),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.green[400],
padding: EdgeInsets.symmetric(vertical: 12.h),
),
),
),
],
),
],
),
);
}
绿色"已掌握"按钮,颜色对比鲜明。点击后自动切换到下一张卡片。
切换卡片逻辑
前后切换的方法:
void _nextCard() {
if (_currentIndex < _cards.length - 1) {
setState(() {
_currentIndex++;
_showAnswer = false;
});
}
}
void _previousCard() {
if (_currentIndex > 0) {
setState(() {
_currentIndex--;
_showAnswer = false;
});
}
}
切换时重置_showAnswer为false,确保新卡片显示正面。边界检查防止索引越界。
标记卡片逻辑
标记掌握程度并切换:
void _markCard(bool mastered) {
if (_currentIndex < _cards.length - 1) {
_nextCard();
} else {
_showCompletionDialog();
}
}
如果不是最后一张就切换到下一张,最后一张标记后弹出完成对话框。
完成对话框
练习完成后的反馈:
void _showCompletionDialog() {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('练习完成!'),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.celebration,
size: 64.sp,
color: Colors.amber
),
SizedBox(height: 16.h),
Text('你已完成 ${_cards.length} 张闪卡的练习'),
],
),
庆祝图标配合完成提示,mainAxisSize: MainAxisSize.min让对话框高度自适应内容。
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
Navigator.pop(context);
},
child: const Text('返回'),
),
ElevatedButton(
onPressed: () {
Navigator.pop(context);
setState(() {
_currentIndex = 0;
_showAnswer = false;
});
},
child: const Text('再练一次'),
),
],
),
);
}
两个按钮:返回上一页或重新开始。重新开始时重置索引和状态从头练习。
小结
闪卡练习的核心是点击翻转和滑动切换的交互设计。AnimatedSwitcher提供平滑的过渡动画,掌握程度按钮帮助用户自我评估学习效果。这种主动回忆的学习方式比被动阅读更有效,能加深记忆。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
更多推荐


所有评论(0)