Flutter中如何从Datepicker选择的生日自动计算年龄?
修复Flutter生日选择后的年龄计算与显示问题
原代码存在的核心问题
calAge方法未使用用户实际选中的生日日期,而是定义了空变量birt,导致年龄计算逻辑从未触发- 界面缺少年龄显示的UI组件,计算结果无法呈现给用户
- 从SharedPreferences读取保存的生日后,未同步触发年龄计算
修复方案
- 修正年龄计算逻辑:直接使用选中的
selectedDate调用age_calculator库计算精确年龄 - 添加年龄展示UI:在界面中新增文本组件,实时显示计算后的年龄信息
- 同步历史数据的年龄计算:读取SharedPreferences中的生日数据后,解析为DateTime并触发年龄计算
完整修复代码
import 'package:age_calculator/age_calculator.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; class BirthdayScreen extends StatefulWidget { const BirthdayScreen({Key? key}) : super(key: key); @override State<BirthdayScreen> createState() => _BirthdayScreenState(); } class _BirthdayScreenState extends State<BirthdayScreen> { @override void initState() { super.initState(); dropdownValueBirthday = birthday.first; checkValueBirthday(); } DateTime? selectedDate; DateTime now = DateTime.now(); void showDatePicker() { DateTime mindate = DateTime(now.year - 2, now.month, now.day - 29); DateTime maxdate = DateTime(now.year - 1, now.month, now.day); showCupertinoModalPopup( context: context, builder: (BuildContext builder) { return Container( height: MediaQuery.of(context).copyWith().size.height * 0.25, color: Colors.white, child: CupertinoDatePicker( mode: CupertinoDatePickerMode.date, initialDateTime: selectedDate ?? mindate, onDateTimeChanged: (value) { if (value != selectedDate) { setState(() { selectedDate = value; dropdownValueBirthday = '${selectedDate?.year}/${selectedDate?.month}/${selectedDate?.day}'; calAge(); }); } }, maximumDate: maxdate, minimumDate: mindate, ), ); }); } String? dropdownValueBirthday; List<String> birthday = [ 'Birthday', ]; checkValueBirthday() { _getDataBirthday(); } _saveDataBirthday(String dropdownValueBirthdayShared) async { SharedPreferences sharedPreferences = await SharedPreferences.getInstance(); sharedPreferences.setString("dataBirthday", dropdownValueBirthdayShared); } _getDataBirthday() async { SharedPreferences sharedPreferences = await SharedPreferences.getInstance(); dropdownValueBirthday = sharedPreferences.getString("dataBirthday") ?? birthday.first; // 解析保存的生日字符串,同步计算年龄 if (dropdownValueBirthday != birthday.first) { try { List<String> dateParts = dropdownValueBirthday!.split('/'); selectedDate = DateTime( int.parse(dateParts[0]), int.parse(dateParts[1]), int.parse(dateParts[2]), ); calAge(); } catch (e) { print('解析生日失败: $e'); } } setState(() {}); } String age = "请选择生日"; DateDuration? duration; // 调用age_calculator计算精确年龄 void calAge() { if (selectedDate != null) { setState(() { duration = AgeCalculator.age(selectedDate!); age = '${duration?.years}岁 ${duration?.months}个月 ${duration?.days}天'; }); } else { age = "请选择生日"; } } @override Widget build(BuildContext context) { return Scaffold( body: Container( padding: const EdgeInsets.symmetric(horizontal: 15), child: Column( children: [ const SizedBox(height: 100), Row( children: <Widget>[ const Icon( Icons.brightness_1, color: Colors.black, size: 10, ), const Padding( padding: EdgeInsets.only(left: 15.0), child: Text("birthday", style: TextStyle( fontSize: 16.0, )), ), Padding( padding: const EdgeInsets.only(left: 25.0), child: SizedBox( width: 110.0, height: 25.0, child: DecoratedBox( decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), color: Colors.white, border: Border.all(color: Colors.grey.shade300), ), child: Center( child: Text( selectedDate == null ? (dropdownValueBirthday ?? birthday.first) : '${selectedDate?.year}/${selectedDate?.month}/${selectedDate?.day}', style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w500), ), ), ), ), ), Padding( padding: const EdgeInsets.only(left: 15.0), child: SizedBox( width: 88.0, height: 25.0, child: MaterialButton( onPressed: showDatePicker, shape: const StadiumBorder(), color: Colors.blue, child: const Text( 'select', style: TextStyle(color: Colors.white, fontSize: 12), ), ), ), ), ], ), // 新增年龄显示组件 Padding( padding: const EdgeInsets.only(top: 30.0), child: Text( age, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600), ), ), const Spacer(), Padding( padding: const EdgeInsets.only(bottom: 30.0), child: SizedBox( width: 160.0, height: 35.0, child: ElevatedButton( style: ButtonStyle( shape: MaterialStateProperty.all<RoundedRectangleBorder>( RoundedRectangleBorder( borderRadius: BorderRadius.circular(18.0), side: const BorderSide( color: Colors.blueAccent, ), ), ), ), onPressed: () { if (dropdownValueBirthday != birthday.first) { _saveDataBirthday(dropdownValueBirthday!); } }, child: const Text('next')), ), ), ], ), ), ); } }
修复细节说明
- 优化
calAge方法:直接使用选中的日期调用第三方库计算精确年龄,包含年、月、日的完整信息 - 同步历史数据:读取保存的生日字符串后解析为DateTime,自动触发年龄计算,保证重启APP后年龄正常显示
- 新增年龄UI:在生日选择区域下方添加醒目的年龄展示文本
- 完善初始值:日期选择器优先使用已选中的日期,提升用户体验
- 增加保存判断:避免默认的"Birthday"文本被存入SharedPreferences
内容的提问来源于stack exchange,提问作者Dasun Dola
相关产品推荐
相关产品推荐

