Flutter for OpenHarmony 视力保护提醒App实战 - 健康建议与护眼知识
本文介绍了健康建议页面的设计与实现,重点展示护眼知识点的卡片式布局。通过Flutter框架构建可滚动的建议列表,每个卡片包含编号、标题和详细内容,采用不同颜色增强视觉效果。页面整合了6个核心护眼知识点,如20-20-20规则、正确坐姿等,通过枚举分类管理建议类型。代码采用模块化设计,包含卡片构建、数据模型等组件,支持后续功能扩展。该设计兼顾美观性与实用性,为用户提供系统化的护眼知识学习体验。

健康建议与护眼知识是应用的重要组成部分,它可以帮助用户了解如何保护眼睛。本文将详细讲解如何实现一个健康建议页面,包括多个护眼知识点的展示和详细说明。
健康建议页面的设计
健康建议页面包含多个建议卡片,每个卡片都展示一个护眼知识点。这样的设计可以让用户系统地学习护眼知识。
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class DailyTipsDetail extends StatelessWidget {
const DailyTipsDetail({super.key});
Widget build(BuildContext context) {
final tips = [
{'title': '20-20-20规则', 'content': '每20分钟,看20英尺外的东西,持续20秒'},
{'title': '正确坐姿', 'content': '保持背部挺直,屏幕在眼睛下方15-20度'},
{'title': '屏幕距离', 'content': '保持50-70厘米的距离,避免过近或过远'},
{'title': '眼睛湿润', 'content': '每分钟眨眼15-20次,保持眼睛湿润'},
{'title': '光线调整', 'content': '避免屏幕反光,使用适当的照明'},
{'title': '定期检查', 'content': '每年进行一次眼睛检查'},
];
return Scaffold(
appBar: AppBar(
title: const Text('健康建议'),
backgroundColor: const Color(0xFFFFC107),
foregroundColor: Colors.white,
),
body: ListView.builder(
padding: EdgeInsets.all(16.w),
itemCount: tips.length,
itemBuilder: (context, index) {
return _buildTipCard(tips[index], index);
},
),
);
}
这段代码定义了DailyTipsDetail无状态组件,包含六个重要的护眼建议。使用ListView.builder创建可滚动的列表,每个建议都通过_buildTipCard方法渲染为卡片。这种设计模式使得代码结构清晰,易于添加或修改建议内容。Scaffold提供了标准的Material Design框架,AppBar使用黄色主题色,与应用的整体设计风格保持一致。
Widget _buildTipCard(Map<String, String> tip, int index) {
final colors = [
const Color(0xFF2196F3),
const Color(0xFF4CAF50),
const Color(0xFFE91E63),
const Color(0xFFFFC107),
const Color(0xFF00BCD4),
const Color(0xFF9C27B0),
];
return 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.1),
blurRadius: 8,
offset: const Offset(0, 2),
),
],
),
代码说明: _buildTipCard方法负责构建每个建议卡片的UI。通过使用颜色数组和模运算,为每个建议分配不同的颜色,增强了视觉效果。圆形编号容器使用半透明的背景色,与编号文字颜色相匹配,形成了统一的视觉风格。BoxShadow添加了阴影效果,使卡片看起来更加立体。height: 1.5设置行高,提高了文本的可读性。
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Container(
width: 40.w,
height: 40.w,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: colors[index % colors.length].withOpacity(0.1),
),
child: Center(
child: Text(
'${index + 1}',
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.bold,
color: colors[index % colors.length],
),
),
),
),
SizedBox(width: 12.w),
Expanded(
child: Text(
tip['title']!,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.bold,
),
),
),
],
),
SizedBox(height: 12.h),
Text(
tip['content']!,
style: TextStyle(
fontSize: 14.sp,
color: Colors.grey[700],
height: 1.5,
),
),
],
),
);
}
}
卡片设计的视觉层次: 这个卡片采用了多层次的视觉设计。编号圆形作为视觉焦点,吸引用户的注意力。标题使用粗体字体,内容使用较小的灰色字体,形成了清晰的信息层次。阴影效果为卡片增加了深度感。颜色的多样性使得不同的建议易于区分。这种设计充分利用了Flutter的布局系统,通过Row和Column的组合实现了复杂的UI布局,同时保持了代码的可读性。
健康建议页面使用ListView.builder来创建一个可滚动的列表。每个建议都显示为一个卡片,包含建议的标题和详细内容。
建议卡片的设计
每个建议卡片都包含一个编号、标题和详细内容。编号使用不同的颜色来区分,这样可以让用户快速识别不同的建议。
卡片使用圆形的编号容器来显示建议的序号,这样可以让页面看起来更加整洁和专业。
护眼知识的内容
健康建议页面包含六个重要的护眼知识点:
- 20-20-20规则 - 这是最著名的护眼规则,每20分钟休息一次
- 正确坐姿 - 保持正确的坐姿可以减少眼睛疲劳
- 屏幕距离 - 保持适当的屏幕距离可以保护眼睛
- 眼睛湿润 - 经常眨眼可以保持眼睛湿润
- 光线调整 - 适当的照明可以减少眼睛疲劳
- 定期检查 - 定期进行眼睛检查可以及早发现问题
建议分类管理
建议分类管理用于组织和管理不同类型的护眼建议。
enum TipCategory {
posture('正确坐姿'),
screenDistance('屏幕距离'),
eyeRest('眼睛休息'),
eyeExercise('眼睛锻炼'),
lighting('光线调整'),
nutrition('营养补充');
final String displayName;
const TipCategory(this.displayName);
}
class TipItem {
final String id;
final String title;
final String content;
final TipCategory category;
final int priority;
final DateTime createdAt;
bool isFavorite;
代码说明: 这部分代码定义了TipCategory枚举和TipItem类,用于管理护眼建议。TipCategory枚举定义了六种建议分类,每个分类都有对应的显示名称。TipItem类表示单条建议,包含id、title、content、category、priority、createdAt和isFavorite属性。toJson()和fromJson()方法支持数据的序列化和反序列化。category.name获取枚举的字符串表示,TipCategory.values.byName()从字符串恢复枚举值。
TipItem({
required this.id,
required this.title,
required this.content,
required this.category,
required this.priority,
required this.createdAt,
this.isFavorite = false,
});
Map<String, dynamic> toJson() {
return {
'id': id,
'title': title,
'content': content,
'category': category.name,
'priority': priority,
'createdAt': createdAt.toIso8601String(),
'isFavorite': isFavorite,
};
}
factory TipItem.fromJson(Map<String, dynamic> json) {
return TipItem(
id: json['id'],
title: json['title'],
content: json['content'],
category: TipCategory.values.byName(json['category']),
priority: json['priority'],
createdAt: DateTime.parse(json['createdAt']),
isFavorite: json['isFavorite'] ?? false,
);
}
}
枚举与数据模型设计: 使用枚举定义分类确保了类型安全,避免了字符串硬编码的错误。TipItem类包含了建议的所有关键信息,包括优先级和收藏状态。isFavorite字段允许用户标记喜欢的建议。通过toJson()和fromJson()方法实现了完整的序列化支持,便于数据持久化和网络传输。这种设计模式是Flutter应用中处理复杂数据结构的标准做法。
class TipCategoryManager {
static final TipCategoryManager _instance = TipCategoryManager._internal();
final Map<TipCategory, List<TipItem>> _tipsByCategory = {};
factory TipCategoryManager() {
return _instance;
}
TipCategoryManager._internal() {
_initializeCategories();
}
void _initializeCategories() {
for (var category in TipCategory.values) {
_tipsByCategory[category] = [];
}
}
void addTip(TipItem tip) {
_tipsByCategory[tip.category]?.add(tip);
}
List<TipItem> getTipsByCategory(TipCategory category) {
return _tipsByCategory[category] ?? [];
}
List<TipItem> getAllTips() {
final allTips = <TipItem>[];
_tipsByCategory.forEach((_, tips) => allTips.addAll(tips));
return allTips..sort((a, b) => b.priority.compareTo(a.priority));
}
List<TipItem> getTipsByPriority(int minPriority) {
return getAllTips().where((tip) => tip.priority >= minPriority).toList();
}
void removeTip(String tipId) {
_tipsByCategory.forEach((_, tips) {
tips.removeWhere((tip) => tip.id == tipId);
});
}
}
代码说明: 这部分代码定义了TipCategoryManager类,采用单例模式管理所有分类的建议。_tipsByCategory是一个Map,键为分类,值为该分类下的建议列表。_initializeCategories()方法在初始化时为每个分类创建空列表。addTip()方法添加新建议到对应的分类。getTipsByCategory()方法获取指定分类的所有建议。getAllTips()方法获取所有建议并按优先级排序。getTipsByPriority()方法获取优先级达到指定值的建议。removeTip()方法根据id删除建议。??操作符提供了安全的空值处理。
分类管理架构: 使用Map数据结构实现了高效的分类存储和查询。_initializeCategories()方法确保了所有分类都被初始化,避免了空指针异常。getAllTips()方法通过forEach遍历所有分类并合并结果,然后按优先级排序。这种设计支持多维度的数据查询,如按分类查询、按优先级查询等。单例模式确保了全局数据的一致性。
建议搜索功能
建议搜索功能允许用户快速查找相关的护眼建议。
class TipSearchEngine {
final TipCategoryManager _categoryManager = TipCategoryManager();
List<TipItem> searchByKeyword(String keyword) {
if (keyword.isEmpty) {
return _categoryManager.getAllTips();
}
final lowerKeyword = keyword.toLowerCase();
return _categoryManager.getAllTips().where((tip) {
return tip.title.toLowerCase().contains(lowerKeyword) ||
tip.content.toLowerCase().contains(lowerKeyword);
}).toList();
}
List<TipItem> searchByCategory(TipCategory category) {
return _categoryManager.getTipsByCategory(category);
}
List<TipItem> searchByMultipleCategories(List<TipCategory> categories) {
final results = <TipItem>[];
for (var category in categories) {
results.addAll(_categoryManager.getTipsByCategory(category));
}
return results;
}
List<TipItem> searchFavoriteTips() {
return _categoryManager.getAllTips().where((tip) => tip.isFavorite).toList();
}
List<TipItem> searchRecentTips(int days) {
final cutoffDate = DateTime.now().subtract(Duration(days: days));
return _categoryManager.getAllTips()
.where((tip) => tip.createdAt.isAfter(cutoffDate))
.toList();
}
}
代码说明: 这部分代码定义了TipSearchEngine类,提供多种搜索功能。searchByKeyword()方法根据关键词在标题和内容中进行模糊搜索,使用toLowerCase()实现不区分大小写的搜索。searchByCategory()方法按分类搜索。searchByMultipleCategories()方法支持多分类搜索。searchFavoriteTips()方法获取所有收藏的建议。searchRecentTips()方法获取指定天数内的新建议。这种设计提供了灵活的搜索选项,满足用户的多样化需求。
搜索引擎设计: 这个搜索引擎采用了多维度搜索策略,支持关键词搜索、分类搜索、多分类搜索、收藏搜索和时间范围搜索。关键词搜索使用toLowerCase()实现不区分大小写的搜索。where()方法进行条件过滤,toList()转换为列表。DateTime.now().subtract()计算截止日期。这种设计提供了强大的搜索能力,用户可以快速找到需要的建议。
建议收藏功能
建议收藏功能允许用户保存喜欢的建议以便快速访问。
class FavoriteTipsManager {
static final FavoriteTipsManager _instance = FavoriteTipsManager._internal();
final List<String> _favoriteIds = [];
factory FavoriteTipsManager() {
return _instance;
}
FavoriteTipsManager._internal();
void addFavorite(String tipId) {
if (!_favoriteIds.contains(tipId)) {
_favoriteIds.add(tipId);
}
}
void removeFavorite(String tipId) {
_favoriteIds.remove(tipId);
}
bool isFavorite(String tipId) {
return _favoriteIds.contains(tipId);
}
List<String> getAllFavorites() {
return List.unmodifiable(_favoriteIds);
}
Future<void> saveFavorites() async {
final prefs = await SharedPreferences.getInstance();
await prefs.setStringList('favorite_tips', _favoriteIds);
}
Future<void> loadFavorites() async {
final prefs = await SharedPreferences.getInstance();
final favorites = prefs.getStringList('favorite_tips') ?? [];
_favoriteIds.clear();
_favoriteIds.addAll(favorites);
}
Future<void> clearFavorites() async {
_favoriteIds.clear();
final prefs = await SharedPreferences.getInstance();
await prefs.remove('favorite_tips');
}
}
代码说明: 这部分代码定义了FavoriteTipsManager类,采用单例模式管理用户的收藏建议。_favoriteIds列表存储所有收藏的建议id。addFavorite()方法添加收藏,检查重复以避免重复收藏。removeFavorite()方法移除收藏。isFavorite()方法检查建议是否已收藏。getAllFavorites()方法返回所有收藏的id列表,使用List.unmodifiable()返回不可修改的副本。saveFavorites()和loadFavorites()方法实现收藏数据的持久化。clearFavorites()方法清除所有收藏。
收藏管理实现: 使用_favoriteIds列表存储收藏的id,而不是完整的对象,这样可以减少内存占用。addFavorite()方法检查重复以避免重复收藏。getAllFavorites()返回不可修改的列表副本,保护了内部数据。异步的saveFavorites()和loadFavorites()方法实现了数据的持久化。??操作符提供了安全的空值处理。这种设计提供了高效的收藏管理。
总结
通过以上的设计,我们实现了一个完整的健康建议系统。包括建议分类管理、搜索功能和收藏功能。用户可以按分类浏览建议、按关键词搜索、收藏喜欢的建议。这样的设计使得用户能够更好地学习护眼知识,并快速访问重要的建议。
在实际应用中,我们可以进一步扩展这个系统,添加建议的详细页面、用户评论、分享功能等。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
更多推荐


所有评论(0)