Flutter 框架跨平台鸿蒙开发 - 植物浇水提醒器:智能管理植物养护
✅ 植物信息管理(增删改查)✅ 16种Emoji图标选择✅ 6大植物分类✅ 智能浇水提醒✅ 一键浇水记录✅ 状态颜色标识✅ Badge徽章提醒✅ Slider周期调节✅ 数据本地持久化。
·
Flutter植物浇水提醒器:智能管理植物养护
项目简介
植物浇水提醒器是一款贴心的Flutter应用,帮助植物爱好者科学管理植物浇水。通过智能提醒功能,确保每株植物都能得到及时的水分补充,让养植物变得更加轻松。
运行效果图




核心功能
- 植物管理:添加、编辑、删除植物信息
- 16种图标:丰富的植物图标选择
- 6大分类:多肉、观叶、开花、水培等分类
- 智能提醒:自动计算下次浇水时间
- 一键浇水:快速记录浇水时间
- 状态标识:颜色区分植物状态
- Badge提醒:需要浇水的植物数量提醒
- 数据持久化:本地保存所有记录
技术特点
- Material Design 3设计风格
- Emoji图标选择器
- Slider滑块调节周期
- 状态颜色区分(红/橙/绿)
- Badge徽章提醒
- 响应式卡片布局
- SharedPreferences数据持久化
核心代码实现
1. 植物数据模型
class Plant {
String id;
String name; // 植物名称
String type; // 植物类型
int wateringInterval; // 浇水周期(天)
DateTime lastWatered; // 上次浇水时间
String location; // 位置
String notes; // 备注
String icon; // 图标
// 计算下次浇水日期
DateTime get nextWateringDate {
return lastWatered.add(Duration(days: wateringInterval));
}
// 判断是否需要浇水
bool get needsWatering {
return DateTime.now().isAfter(nextWateringDate);
}
// 距离下次浇水天数
int get daysUntilWatering {
return nextWateringDate.difference(DateTime.now()).inDays;
}
}
模型字段说明:
| 字段 | 类型 | 说明 |
|---|---|---|
| id | String | 唯一标识符 |
| name | String | 植物名称 |
| type | String | 植物类型 |
| wateringInterval | int | 浇水周期(天) |
| lastWatered | DateTime | 上次浇水时间 |
| location | String | 摆放位置 |
| notes | String | 养护备注 |
| icon | String | Emoji图标 |
计算属性:
nextWateringDate:下次浇水日期needsWatering:是否需要浇水daysUntilWatering:距离下次浇水天数
2. 状态判断与颜色
Color statusColor;
String statusText;
IconData statusIcon;
if (plant.needsWatering) {
statusColor = Colors.red;
statusText = '需要浇水';
statusIcon = Icons.water_drop;
} else if (plant.daysUntilWatering <= 1) {
statusColor = Colors.orange;
statusText = '即将浇水';
statusIcon = Icons.schedule;
} else {
statusColor = Colors.green;
statusText = '状态良好';
statusIcon = Icons.check_circle;
}
状态级别:
- 🔴 需要浇水:已超过浇水时间
- 🟠 即将浇水:1天内需要浇水
- 🟢 状态良好:还有时间
3. Emoji图标选择器
final List<String> _icons = [
'🌱', '🌿', '🌵', '🌴', '🌳', '🌲', '🌾',
'🌺', '🌸', '🌼', '🌻', '🌷', '🌹', '🪴', '🍀'
];
Widget _buildIconSelector() {
return Wrap(
spacing: 8,
runSpacing: 8,
children: _icons.map((icon) {
return InkWell(
onTap: () {
setState(() {
_icon = icon;
});
},
child: Container(
width: 50,
height: 50,
decoration: BoxDecoration(
color: _icon == icon
? Colors.green.withValues(alpha: 0.2)
: Colors.grey.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: _icon == icon ? Colors.green : Colors.transparent,
width: 2,
),
),
child: Center(
child: Text(icon, style: const TextStyle(fontSize: 28)),
),
),
);
}).toList(),
);
}
4. Slider滑块调节周期
Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
const Text('浇水周期(天)'),
Row(
children: [
IconButton(
icon: const Icon(Icons.remove_circle_outline),
onPressed: () {
setState(() {
_wateringInterval = (_wateringInterval - 1).clamp(1, 30);
});
},
),
Expanded(
child: Slider(
value: _wateringInterval.toDouble(),
min: 1,
max: 30,
divisions: 29,
label: '$_wateringInterval天',
onChanged: (value) {
setState(() {
_wateringInterval = value.toInt();
});
},
),
),
IconButton(
icon: const Icon(Icons.add_circle_outline),
onPressed: () {
setState(() {
_wateringInterval = (_wateringInterval + 1).clamp(1, 30);
});
},
),
],
),
Text(
'每 $_wateringInterval 天浇一次水',
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.blue,
),
),
],
),
),
)
Slider参数说明:
value:当前值min:最小值(1天)max:最大值(30天)divisions:分段数(29段)label:显示标签onChanged:值变化回调
5. 一键浇水功能
void _waterPlant(Plant plant) {
setState(() {
plant.lastWatered = DateTime.now(); // 更新浇水时间
});
_savePlants(); // 保存数据
// 显示提示
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('已为《${plant.name}》浇水'),
backgroundColor: Colors.green,
),
);
}
// UI按钮
OutlinedButton.icon(
onPressed: () => _waterPlant(plant),
icon: const Icon(Icons.water_drop),
label: const Text('浇水'),
style: OutlinedButton.styleFrom(
foregroundColor: Colors.blue,
),
)
6. Badge徽章提醒
// 获取需要浇水的植物
List<Plant> get _needsWateringPlants {
return _plants.where((p) => p.needsWatering).toList();
}
// 显示Badge
final needsWateringCount = _needsWateringPlants.length;
if (needsWateringCount > 0)
IconButton(
icon: Badge(
label: Text('$needsWateringCount'),
child: const Icon(Icons.water_drop),
),
onPressed: _showWateringReminders,
),
7. 浇水提醒对话框
void _showWateringReminders() {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('浇水提醒'),
content: SingleChildScrollView(
child: Column(
children: [
const Text('以下植物需要浇水:'),
..._needsWateringPlants.map((plant) => Row(
children: [
Text(plant.icon),
Expanded(child: Text(plant.name)),
TextButton(
onPressed: () {
_waterPlant(plant);
Navigator.pop(context);
},
child: const Text('浇水'),
),
],
)),
],
),
),
),
);
}
技术要点详解
Slider组件
Slider是Material Design的滑块组件:
Slider(
value: _currentValue,
min: 0,
max: 100,
divisions: 10, // 分段数
label: '$_currentValue', // 显示标签
onChanged: (value) {
setState(() {
_currentValue = value;
});
},
)
常用属性:
value:当前值(必需)min:最小值max:最大值divisions:分段数(离散值)label:拖动时显示的标签activeColor:激活颜色inactiveColor:未激活颜色
Wrap组件
Wrap是自动换行的布局组件:
Wrap(
spacing: 8, // 主轴间距
runSpacing: 8, // 交叉轴间距
alignment: WrapAlignment.start,
children: [
Chip(label: Text('标签1')),
Chip(label: Text('标签2')),
Chip(label: Text('标签3')),
],
)
与Row的区别:
- Row:单行,超出会溢出
- Wrap:自动换行,适合标签云
SnackBar提示
SnackBar是底部弹出提示:
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('操作成功'),
duration: Duration(seconds: 2),
backgroundColor: Colors.green,
action: SnackBarAction(
label: '撤销',
onPressed: () {
// 撤销操作
},
),
),
);
DateTime计算
常用的日期时间计算:
// 加减时间
final tomorrow = DateTime.now().add(Duration(days: 1));
final yesterday = DateTime.now().subtract(Duration(days: 1));
// 计算时间差
final difference = date2.difference(date1);
final days = difference.inDays;
final hours = difference.inHours;
// 判断先后
if (date1.isAfter(date2)) { }
if (date1.isBefore(date2)) { }
if (date1.isAtSameMomentAs(date2)) { }
常见植物浇水周期
浇水周期参考表
| 植物类型 | 浇水周期 | 养护要点 |
|---|---|---|
| 多肉植物 | 7-14天 | 少浇水,避免积水 |
| 绿萝 | 3-5天 | 保持土壤湿润 |
| 仙人掌 | 14-30天 | 耐旱,少浇水 |
| 吊兰 | 3-5天 | 喜湿润环境 |
| 发财树 | 7-10天 | 不宜过湿 |
| 虎皮兰 | 7-14天 | 耐旱植物 |
| 芦荟 | 10-14天 | 少浇水 |
| 富贵竹 | 水培每周换水 | 保持水质清洁 |
| 君子兰 | 5-7天 | 见干见湿 |
| 常春藤 | 3-5天 | 喜湿润 |
浇水原则
- 见干见湿:等土壤表面干了再浇
- 浇则浇透:浇水要浇到底部有水流出
- 季节调整:夏季多浇,冬季少浇
- 观察植物:叶子发蔫说明缺水
- 避免积水:积水容易烂根
功能扩展建议
1. 浇水历史记录
记录每次浇水的详细信息:
class WateringRecord {
String plantId;
DateTime wateredTime;
String notes;
}
class Plant {
// ... 其他字段
List<WateringRecord> wateringHistory;
}
// 显示历史
Widget _buildWateringHistory(Plant plant) {
return ListView.builder(
itemCount: plant.wateringHistory.length,
itemBuilder: (context, index) {
final record = plant.wateringHistory[index];
return ListTile(
leading: const Icon(Icons.water_drop),
title: Text('${record.wateredTime.year}-${record.wateredTime.month}-${record.wateredTime.day}'),
subtitle: Text(record.notes),
);
},
);
}
2. 施肥提醒
添加施肥管理功能:
class Plant {
// ... 其他字段
int fertilizingInterval; // 施肥周期
DateTime lastFertilized; // 上次施肥时间
DateTime get nextFertilizingDate {
return lastFertilized.add(Duration(days: fertilizingInterval));
}
bool get needsFertilizing {
return DateTime.now().isAfter(nextFertilizingDate);
}
}
// 施肥按钮
OutlinedButton.icon(
onPressed: () => _fertilizePlant(plant),
icon: const Icon(Icons.grass),
label: const Text('施肥'),
)
3. 植物照片
添加植物照片功能:
import 'package:image_picker/image_picker.dart';
class Plant {
// ... 其他字段
String? photoPath;
}
Future<void> _takePhoto() async {
final picker = ImagePicker();
final pickedFile = await picker.pickImage(source: ImageSource.camera);
if (pickedFile != null) {
setState(() {
_photoPath = pickedFile.path;
});
}
}
// 显示照片
if (plant.photoPath != null)
Image.file(
File(plant.photoPath!),
width: 100,
height: 100,
fit: BoxFit.cover,
)
4. 生长记录
记录植物生长情况:
class GrowthRecord {
DateTime date;
double height; // 高度(cm)
int leafCount; // 叶片数
String condition; // 生长状况
String photo; // 照片路径
}
class Plant {
// ... 其他字段
List<GrowthRecord> growthRecords;
}
// 生长曲线图
import 'package:fl_chart/fl_chart.dart';
Widget _buildGrowthChart(Plant plant) {
return LineChart(
LineChartData(
lineBarsData: [
LineChartBarData(
spots: plant.growthRecords
.asMap()
.entries
.map((e) => FlSpot(
e.key.toDouble(),
e.value.height,
))
.toList(),
isCurved: true,
color: Colors.green,
),
],
),
);
}
5. 天气关联
根据天气调整浇水提醒:
import 'package:weather/weather.dart';
class WeatherService {
Future<Weather> getCurrentWeather() async {
// 获取当前天气
}
int adjustWateringInterval(int baseInterval, Weather weather) {
// 晴天:减少周期
if (weather.weatherMain == 'Clear') {
return (baseInterval * 0.8).toInt();
}
// 雨天:增加周期
if (weather.weatherMain == 'Rain') {
return (baseInterval * 1.2).toInt();
}
return baseInterval;
}
}
6. 本地通知
定时推送浇水提醒:
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
class NotificationService {
final FlutterLocalNotificationsPlugin _notifications =
FlutterLocalNotificationsPlugin();
Future<void> scheduleWateringReminder(Plant plant) async {
await _notifications.zonedSchedule(
plant.id.hashCode,
'浇水提醒',
'${plant.name}需要浇水了',
tz.TZDateTime.from(plant.nextWateringDate, tz.local),
const NotificationDetails(
android: AndroidNotificationDetails(
'watering_channel',
'浇水提醒',
importance: Importance.high,
),
),
uiLocalNotificationDateInterpretation:
UILocalNotificationDateInterpretation.absoluteTime,
);
}
}
常见问题解答
Q1: 如何批量浇水?
A: 添加批量操作功能:
void _waterAllNeededPlants() {
final needsWatering = _plants.where((p) => p.needsWatering).toList();
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('批量浇水'),
content: Text('确定要为${needsWatering.length}株植物浇水吗?'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('取消'),
),
FilledButton(
onPressed: () {
setState(() {
for (var plant in needsWatering) {
plant.lastWatered = DateTime.now();
}
});
_savePlants();
Navigator.pop(context);
},
child: const Text('确定'),
),
],
),
);
}
Q2: 如何设置不同季节的浇水周期?
A: 添加季节调整功能:
class Plant {
// ... 其他字段
int springInterval; // 春季周期
int summerInterval; // 夏季周期
int autumnInterval; // 秋季周期
int winterInterval; // 冬季周期
int get currentInterval {
final month = DateTime.now().month;
if (month >= 3 && month <= 5) return springInterval;
if (month >= 6 && month <= 8) return summerInterval;
if (month >= 9 && month <= 11) return autumnInterval;
return winterInterval;
}
}
Q3: 如何导出植物清单?
A: 实现数据导出功能:
import 'package:csv/csv.dart';
import 'package:path_provider/path_provider.dart';
Future<void> exportToCSV(List<Plant> plants) async {
List<List<dynamic>> rows = [
['名称', '类型', '浇水周期', '上次浇水', '下次浇水', '位置']
];
for (var plant in plants) {
rows.add([
plant.name,
plant.type,
'${plant.wateringInterval}天',
'${plant.lastWatered.year}-${plant.lastWatered.month}-${plant.lastWatered.day}',
'${plant.nextWateringDate.year}-${plant.nextWateringDate.month}-${plant.nextWateringDate.day}',
plant.location,
]);
}
String csv = const ListToCsvConverter().convert(rows);
final directory = await getApplicationDocumentsDirectory();
final file = File('${directory.path}/plants.csv');
await file.writeAsString(csv);
}
Q4: 如何添加植物百科?
A: 集成植物知识库:
class PlantEncyclopedia {
String name;
String description;
String wateringTips;
String lightRequirement;
String temperatureRange;
List<String> commonIssues;
}
final encyclopedia = {
'绿萝': PlantEncyclopedia(
name: '绿萝',
description: '常见的室内观叶植物',
wateringTips: '保持土壤湿润,3-5天浇一次水',
lightRequirement: '散射光,避免直射',
temperatureRange: '15-30℃',
commonIssues: ['叶子发黄:浇水过多', '叶尖干枯:空气干燥'],
),
};
// 显示百科
void _showEncyclopedia(String plantName) {
final info = encyclopedia[plantName];
if (info != null) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text(info.name),
content: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('简介:${info.description}'),
Text('浇水:${info.wateringTips}'),
Text('光照:${info.lightRequirement}'),
Text('温度:${info.temperatureRange}'),
],
),
),
),
);
}
}
项目总结
实现的功能
✅ 植物信息管理(增删改查)
✅ 16种Emoji图标选择
✅ 6大植物分类
✅ 智能浇水提醒
✅ 一键浇水记录
✅ 状态颜色标识
✅ Badge徽章提醒
✅ Slider周期调节
✅ 数据本地持久化
技术亮点
- Emoji图标:丰富的植物图标选择
- Slider滑块:直观的周期调节
- 智能提醒:自动计算浇水时间
- 一键浇水:快速记录操作
- 状态可视化:颜色区分植物状态
- Badge提醒:醒目的数量标识
- 数据持久化:完整的JSON序列化
应用场景
- 🌱 家庭植物养护
- 🏢 办公室绿植管理
- 🌿 阳台花园管理
- 🪴 多肉植物收藏
- 🌺 花卉爱好者
- 🌳 园艺工作者
植物浇水提醒器是一款实用的植物养护应用,通过智能提醒和便捷操作,让养植物变得更加轻松愉快,帮助每株植物都能茁壮成长。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
更多推荐




所有评论(0)