flutter_for_openharmony家庭药箱管理app实战+用药知识实现
本文介绍了Flutter for OpenHarmony应用中用药知识功能的实现方案。该功能通过卡片式列表展示药品储存、用药安全、药物相互作用等六大主题,每个主题配有专属图标和颜色标识。点击卡片可跳转至详情页查看Markdown格式的详细内容。页面采用响应式布局设计,包含知识分类管理、内容分级展示等特性,为用户提供结构清晰、专业可靠的药品使用指导。实现代码展示了列表构建、卡片样式和内容组织的具体方

用药知识功能为用户提供了丰富的药品使用和储存知识,帮助用户安全合理地使用药品。本文将介绍如何在Flutter for OpenHarmony应用中实现用药知识功能,包括知识列表展示、分类管理、详情页面跳转等特性。
功能设计思路
用药知识页面包含多个知识主题,每个主题都有标题、副标题、图标和详细内容。主题涵盖药品储存、用药安全、药物相互作用、儿童用药、老年人用药、过期药品处理等方面。用户点击某个主题可以查看详细的知识内容,内容使用Markdown格式展示,层次分明。
页面采用列表布局,每个知识主题是一个卡片。卡片左侧是带背景色的图标,中间是标题和副标题,右侧是右箭头。不同主题使用不同的颜色和图标,让页面更加生动。
页面结构实现
页面使用无状态组件,知识数据直接定义在build方法中:
Widget build(BuildContext context) {
final knowledgeList = [
{
'title': '药品储存指南',
'subtitle': '正确储存药品,保证药效',
'icon': Icons.inventory_2,
'color': Colors.blue,
'content': '''
# 药品储存指南
## 一般储存原则
1. **避光保存**:大多数药品应避免阳光直射
2. **阴凉干燥**:保持储存环境干燥,避免潮湿
3. **密封保存**:开封后注意密封,防止受潮变质
## 温度要求
- **常温保存**:10-30°C
- **阴凉保存**:不超过20°C
- **冷藏保存**:2-8°C(如胰岛素、部分眼药水)
''',
},
// 更多知识主题...
];
return Scaffold(
appBar: AppBar(title: const Text('用药知识')),
body: ListView.builder(
padding: EdgeInsets.all(16.w),
itemCount: knowledgeList.length,
itemBuilder: (context, index) {
final item = knowledgeList[index];
return GestureDetector(
onTap: () => Get.to(() => KnowledgeDetailScreen(
title: item['title'] as String,
content: item['content'] as String,
)),
child: Container(
margin: EdgeInsets.only(bottom: 12.h),
padding: EdgeInsets.all(16.w),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12.r),
boxShadow: [
BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 2)),
],
),
child: Row(
children: [
Container(
width: 48.w,
height: 48.w,
decoration: BoxDecoration(
color: (item['color'] as Color).withOpacity(0.1),
borderRadius: BorderRadius.circular(12.r),
),
child: Icon(item['icon'] as IconData, color: item['color'] as Color, size: 24.sp),
),
SizedBox(width: 12.w),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(item['title'] as String,
style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.bold)),
SizedBox(height: 4.h),
Text(item['subtitle'] as String,
style: TextStyle(fontSize: 12.sp, color: Colors.grey[600])),
],
),
),
const Icon(Icons.chevron_right, color: Colors.grey),
],
),
),
);
},
),
);
}
知识数据使用Map列表存储,每个Map包含标题、副标题、图标、颜色和内容。使用ListView.builder构建列表,每个列表项是一个可点击的卡片。点击卡片会跳转到知识详情页面,传递标题和内容参数。
知识卡片设计
每个知识主题的卡片采用统一的设计风格:
child: Container(
margin: EdgeInsets.only(bottom: 12.h),
padding: EdgeInsets.all(16.w),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12.r),
boxShadow: [
BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 2)),
],
),
child: Row(
children: [
Container(
width: 48.w,
height: 48.w,
decoration: BoxDecoration(
color: (item['color'] as Color).withOpacity(0.1),
borderRadius: BorderRadius.circular(12.r),
),
child: Icon(item['icon'] as IconData, color: item['color'] as Color, size: 24.sp),
),
SizedBox(width: 12.w),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(item['title'] as String,
style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.bold)),
SizedBox(height: 4.h),
Text(item['subtitle'] as String,
style: TextStyle(fontSize: 12.sp, color: Colors.grey[600])),
],
),
),
const Icon(Icons.chevron_right, color: Colors.grey),
],
),
),
卡片使用白色背景和浅色阴影,视觉上清爽舒适。左侧图标使用半透明背景色,与图标颜色相呼应。中间是标题和副标题的垂直布局,右侧是灰色右箭头提示可点击。
知识内容组织
知识内容使用Markdown格式编写,层次分明:
'content': '''
# 药品储存指南
## 一般储存原则
1. **避光保存**:大多数药品应避免阳光直射
2. **阴凉干燥**:保持储存环境干燥,避免潮湿
3. **密封保存**:开封后注意密封,防止受潮变质
## 温度要求
- **常温保存**:10-30°C
- **阴凉保存**:不超过20°C
- **冷藏保存**:2-8°C(如胰岛素、部分眼药水)
## 特殊药品储存
- **液体药品**:开封后注意有效期,通常较短
- **栓剂**:夏季建议冷藏保存
- **喷雾剂**:避免高温和阳光直射
''',
内容使用一级标题、二级标题、列表、加粗等Markdown语法,让信息结构清晰。每个主题都包含多个小节,内容详实专业。这种格式化的内容在详情页面中会被正确渲染,阅读体验良好。
多主题设计
页面包含六个知识主题,每个主题使用不同的颜色和图标:
{
'title': '药品储存指南',
'subtitle': '正确储存药品,保证药效',
'icon': Icons.inventory_2,
'color': Colors.blue,
},
{
'title': '用药安全须知',
'subtitle': '安全用药,健康生活',
'icon': Icons.security,
'color': Colors.green,
},
{
'title': '常见药物相互作用',
'subtitle': '了解药物配伍禁忌',
'icon': Icons.warning,
'color': Colors.orange,
},
{
'title': '儿童用药指南',
'subtitle': '儿童安全用药知识',
'icon': Icons.child_care,
'color': Colors.pink,
},
{
'title': '老年人用药注意',
'subtitle': '老年人安全用药要点',
'icon': Icons.elderly,
'color': Colors.purple,
},
{
'title': '过期药品处理',
'subtitle': '正确处理过期药品',
'icon': Icons.delete_forever,
'color': Colors.red,
},
药品储存用蓝色和库存图标,用药安全用绿色和安全图标,药物相互作用用橙色和警告图标,儿童用药用粉色和儿童图标,老年人用药用紫色和老年人图标,过期药品处理用红色和删除图标。这种设计让每个主题都有鲜明的视觉特征,用户可以快速识别。
页面跳转
点击知识卡片会跳转到详情页面:
return GestureDetector(
onTap: () => Get.to(() => KnowledgeDetailScreen(
title: item['title'] as String,
content: item['content'] as String,
)),
child: Container(
// 卡片内容
),
);
使用GestureDetector包裹卡片,点击时通过Get.to跳转到详情页面。详情页面接收标题和内容两个参数,使用Markdown渲染器展示内容。这种设计让知识的查看体验流畅自然。
技术要点
数据驱动:知识数据使用Map列表存储,通过ListView.builder动态构建UI。这种设计让添加新知识主题变得非常简单,只需在列表中添加新的Map即可。
Markdown格式:知识内容使用Markdown格式编写,支持标题、列表、加粗等语法。在详情页面中使用Markdown渲染器展示,让内容层次分明,阅读体验良好。
视觉设计:每个主题使用不同的颜色和图标,让页面更加生动。图标背景使用半透明颜色,与图标颜色相呼应,视觉效果统一协调。
交互设计:卡片采用可点击设计,右侧有右箭头提示。点击后跳转到详情页面,交互流畅自然。用户可以方便地浏览和学习各类用药知识。
知识详情页面实现
知识详情页面使用Markdown渲染器展示内容:
class KnowledgeDetailScreen extends StatelessWidget {
final String title;
final String content;
const KnowledgeDetailScreen({
super.key,
required this.title,
required this.content,
});
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(title)),
body: SingleChildScrollView(
padding: EdgeInsets.all(16.w),
child: MarkdownBody(
data: content,
styleSheet: MarkdownStyleSheet(
h1: TextStyle(fontSize: 22.sp, fontWeight: FontWeight.bold),
h2: TextStyle(fontSize: 18.sp, fontWeight: FontWeight.bold),
p: TextStyle(fontSize: 14.sp, height: 1.6),
listBullet: TextStyle(fontSize: 14.sp),
),
),
),
);
}
}
详情页面接收标题和内容两个参数。使用flutter_markdown库的MarkdownBody组件渲染Markdown内容。通过MarkdownStyleSheet自定义样式,设置标题大小、段落行高等属性。SingleChildScrollView让长内容可以滚动查看。
搜索功能实现
为知识列表添加搜索功能,方便用户快速找到需要的内容:
class _MedicineKnowledgeScreenState extends State<MedicineKnowledgeScreen> {
String _searchQuery = '';
final TextEditingController _searchController = TextEditingController();
List<Map<String, dynamic>> _filterKnowledge(List<Map<String, dynamic>> list) {
if (_searchQuery.isEmpty) return list;
return list.where((item) {
final title = item['title'] as String;
final subtitle = item['subtitle'] as String;
final content = item['content'] as String;
return title.contains(_searchQuery) ||
subtitle.contains(_searchQuery) ||
content.contains(_searchQuery);
}).toList();
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('用药知识'),
bottom: PreferredSize(
preferredSize: Size.fromHeight(56.h),
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h),
child: TextField(
controller: _searchController,
decoration: InputDecoration(
hintText: '搜索知识...',
prefixIcon: const Icon(Icons.search),
filled: true,
fillColor: Colors.white,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.r),
borderSide: BorderSide.none,
),
),
onChanged: (v) => setState(() => _searchQuery = v),
),
),
),
),
body: ListView.builder(
padding: EdgeInsets.all(16.w),
itemCount: _filterKnowledge(knowledgeList).length,
itemBuilder: (context, index) {
final item = _filterKnowledge(knowledgeList)[index];
return _buildKnowledgeCard(item);
},
),
);
}
}
搜索框放置在AppBar的bottom区域,始终可见。用户输入时实时过滤知识列表,搜索范围包括标题、副标题和内容。这种设计让用户可以快速定位到需要的知识主题。
收藏功能实现
为知识添加收藏功能,方便用户保存常用内容:
Set<String> _favorites = {};
Widget _buildKnowledgeCard(Map<String, dynamic> item) {
final title = item['title'] as String;
final isFavorite = _favorites.contains(title);
return GestureDetector(
onTap: () => Get.to(() => KnowledgeDetailScreen(
title: title,
content: item['content'] as String,
)),
child: Container(
margin: EdgeInsets.only(bottom: 12.h),
padding: EdgeInsets.all(16.w),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12.r),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 10,
offset: const Offset(0, 2),
),
],
),
child: Row(
children: [
// 图标和内容...
IconButton(
icon: Icon(
isFavorite ? Icons.star : Icons.star_border,
color: isFavorite ? Colors.amber : Colors.grey,
),
onPressed: () {
setState(() {
if (isFavorite) {
_favorites.remove(title);
} else {
_favorites.add(title);
}
});
},
),
],
),
),
);
}
使用Set存储收藏的知识标题。卡片右侧添加收藏按钮,点击切换收藏状态。已收藏的知识显示黄色实心星星,未收藏的显示灰色空心星星。收藏状态可以持久化存储到本地,下次打开应用时恢复。
阅读进度追踪
追踪用户的阅读进度,显示已读和未读状态:
Set<String> _readItems = {};
Widget _buildReadIndicator(String title) {
final isRead = _readItems.contains(title);
return Container(
width: 8.w,
height: 8.w,
decoration: BoxDecoration(
color: isRead ? Colors.green : Colors.orange,
shape: BoxShape.circle,
),
);
}
void _markAsRead(String title) {
setState(() => _readItems.add(title));
_saveReadProgress();
}
使用小圆点指示阅读状态,绿色表示已读,橙色表示未读。当用户进入详情页面时,自动标记为已读。阅读进度保存到本地存储,用户可以清楚地看到哪些知识还没有学习。
分类筛选功能
添加分类筛选,让用户可以按类别查看知识:
String _selectedCategory = '全部';
final List<String> _categories = ['全部', '储存', '安全', '特殊人群', '处理'];
Widget _buildCategoryFilter() {
return SizedBox(
height: 40.h,
child: ListView.builder(
scrollDirection: Axis.horizontal,
padding: EdgeInsets.symmetric(horizontal: 16.w),
itemCount: _categories.length,
itemBuilder: (context, index) {
final category = _categories[index];
final isSelected = category == _selectedCategory;
return GestureDetector(
onTap: () => setState(() => _selectedCategory = category),
child: Container(
margin: EdgeInsets.only(right: 8.w),
padding: EdgeInsets.symmetric(horizontal: 16.w),
decoration: BoxDecoration(
color: isSelected ? const Color(0xFF00897B) : Colors.grey[200],
borderRadius: BorderRadius.circular(20.r),
),
alignment: Alignment.center,
child: Text(
category,
style: TextStyle(
color: isSelected ? Colors.white : Colors.grey[700],
fontSize: 14.sp,
),
),
),
);
},
),
);
}
分类筛选使用水平滚动的标签列表。选中的分类使用主题色背景和白色文字,未选中的使用灰色背景。点击分类标签会筛选出对应类别的知识,方便用户按需学习。
字体大小调节
为详情页面添加字体大小调节功能,适应不同用户的阅读习惯:
double _fontSize = 14.0;
Widget _buildFontSizeControl() {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
icon: const Icon(Icons.text_decrease),
onPressed: () {
if (_fontSize > 12) {
setState(() => _fontSize -= 2);
}
},
),
Text('字体大小', style: TextStyle(fontSize: 14.sp)),
IconButton(
icon: const Icon(Icons.text_increase),
onPressed: () {
if (_fontSize < 20) {
setState(() => _fontSize += 2);
}
},
),
],
);
}
字体大小调节控件放在详情页面顶部或底部。用户可以点击加减按钮调整字体大小,范围限制在12-20之间。字体大小设置可以保存到本地,下次打开时自动应用。这个功能对老年用户特别友好。
总结
用药知识功能通过丰富的知识内容和友好的交互设计,为用户提供了实用的用药指导。从药品储存到用药安全,从特殊人群用药到药品处理,涵盖了用药的各个方面。这种知识普及功能让应用不仅是管理工具,更是健康教育平台,帮助用户建立正确的用药观念。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
更多推荐
所有评论(0)