使用Dart/Flutter比较两个时间输入值计算时长并输出的实现方法
完整实现代码
import 'package:flutter/material.dart'; class ActivityLog extends StatefulWidget { @override _ActivityLogState createState() => _ActivityLogState(); } class _ActivityLogState extends State<ActivityLog> { final TextEditingController _startController = TextEditingController(); final TextEditingController _endController = TextEditingController(); String duration = '0000'; // 计算时间差核心方法 void _calculateDuration() { final startStr = _startController.text.trim(); final endStr = _endController.text.trim(); // 输入长度校验 if (startStr.length != 4 || endStr.length != 4) { setState(() { duration = '0000'; }); return; } try { // 拆分输入的时分并转数字 int startHour = int.parse(startStr.substring(0, 2)); int startMinute = int.parse(startStr.substring(2, 4)); int endHour = int.parse(endStr.substring(0, 2)); int endMinute = int.parse(endStr.substring(2, 4)); // 时分范围合法性校验 if (startHour < 0 || startHour > 23 || startMinute < 0 || startMinute > 59 || endHour < 0 || endHour > 23 || endMinute < 0 || endMinute > 59) { setState(() { duration = '0000'; }); return; } // 构造同日期的DateTime对象,日期不影响当日时间差计算 final baseDate = DateTime.now(); final startTime = DateTime(baseDate.year, baseDate.month, baseDate.day, startHour, startMinute); DateTime endTime = DateTime(baseDate.year, baseDate.month, baseDate.day, endHour, endMinute); // 跨天班次兼容:结束时间早于开始时间时自动给结束时间加1天,不需要可以删除这段 if (endTime.isBefore(startTime)) { endTime = endTime.add(const Duration(days: 1)); } // 计算时间差并格式化为hhmm格式 final diff = endTime.difference(startTime); final formatHours = diff.inHours.remainder(24).toString().padLeft(2, '0'); final formatMinutes = diff.inMinutes.remainder(60).toString().padLeft(2, '0'); setState(() { duration = '$formatHours$formatMinutes'; }); } catch (e) { // 非数字输入异常兜底 setState(() { duration = '0000'; }); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Activity Log'), ), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ TextField( controller: _startController, maxLength: 4, maxLines: 1, keyboardType: TextInputType.datetime, decoration: const InputDecoration( labelText: 'Start time', hintText: 'hhmm', counterText: '', ), // 点击键盘提交按钮触发计算 onSubmitted: (_) => _calculateDuration(), // 输入框失去焦点触发计算 onEditingComplete: _calculateDuration, ), TextField( controller: _endController, maxLength: 4, maxLines: 1, keyboardType: TextInputType.datetime, decoration: const InputDecoration( labelText: 'Finish time', hintText: 'hhmm', counterText: '', ), onSubmitted: (_) => _calculateDuration(), onEditingComplete: _calculateDuration, ), const SizedBox(height: 20), Text('Duration: $duration'), ], ), ), ); } }
关键逻辑说明
- 输入值获取:直接通过
TextEditingController.text即可拿到输入框的实时内容,你之前已经正确声明了控制器,直接调用即可 - 触发时机:给
TextField绑定onSubmitted和onEditingComplete两个回调,完全符合你要求的触发场景 - 异常兼容:代码中加了输入长度校验、时分范围校验、非数字输入异常捕获,避免非法输入导致的崩溃
- 跨天支持:默认支持结束时间早于开始时间的跨天班次计算,不需要可以直接删掉对应代码段即可
内容的提问来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

