You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 11:45:05