123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- import 'dart:async';
- import 'package:flutter/material.dart';
- import 'package:flutter_screenutil/flutter_screenutil.dart';
- class StopwatchPage extends StatefulWidget {
- @override
- State<StopwatchPage> createState() => _StopwatchPageState();
- }
- class _StopwatchPageState extends State<StopwatchPage> {
- bool _isRunning = false;
- Stopwatch _stopwatch = Stopwatch();
- Timer? _timer;
- List<String> _laps = [];
-
- @override
- void initState() {
- super.initState();
- }
- @override
- void dispose() {
- _timer?.cancel();
- super.dispose();
- }
- void _startStop() {
- setState(() {
- if (_isRunning) {
- _isRunning = false;
- _timer?.cancel();
- _stopwatch.stop();
- } else {
- _isRunning = true;
- _stopwatch.start();
- _timer = Timer.periodic(Duration(milliseconds: 10), (timer) {
- setState(() {});
- });
- }
- });
- }
- void _resetStopwatch() {
- setState(() {
- _stopwatch.reset();
- _laps.clear();
- });
- }
- void _addLap() {
- if (_isRunning) {
- setState(() {
- _laps.insert(0, _formatTime(_stopwatch.elapsedMilliseconds));
- });
- }
- }
- String _formatTime(int milliseconds) {
- int hundreds = (milliseconds / 10).truncate() % 100;
- int seconds = (milliseconds / 1000).truncate() % 60;
- int minutes = (milliseconds / 60000).truncate() % 60;
- int hours = (milliseconds / 3600000).truncate();
- String hoursStr = hours > 0 ? '${hours.toString().padLeft(2, '0')}:' : '';
- String minutesStr = minutes.toString().padLeft(2, '0');
- String secondsStr = seconds.toString().padLeft(2, '0');
- String hundredsStr = hundreds.toString().padLeft(2, '0');
- return '$hoursStr$minutesStr:$secondsStr.$hundredsStr';
- }
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- backgroundColor: Colors.white,
- body: Column(
- children: [
- SizedBox(height: 50.h),
- // Stopwatch display
- Text(
- _formatTime(_stopwatch.elapsedMilliseconds),
- style: TextStyle(
- fontSize: 60.sp,
- fontWeight: FontWeight.bold,
- fontFamily: 'monospace',
- ),
- ),
- SizedBox(height: 30.h),
- // Controls
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceEvenly,
- children: [
- _buildControlButton(
- icon: _isRunning ? Icons.pause : Icons.play_arrow,
- label: _isRunning ? 'Stop' : 'Start',
- onPressed: _startStop,
- color: _isRunning ? Colors.red : Colors.green,
- ),
- _buildControlButton(
- icon: Icons.refresh,
- label: 'Reset',
- onPressed: _stopwatch.elapsedMilliseconds > 0 ? _resetStopwatch : null,
- color: Colors.blue,
- ),
- _buildControlButton(
- icon: Icons.flag,
- label: 'Lap',
- onPressed: _isRunning ? _addLap : null,
- color: Colors.orange,
- ),
- ],
- ),
- SizedBox(height: 20.h),
- // Laps
- Expanded(
- child: _laps.isEmpty
- ? Center(
- child: Text(
- 'No laps recorded',
- style: TextStyle(
- fontSize: 16.sp,
- color: Colors.grey,
- ),
- ),
- )
- : ListView.builder(
- itemCount: _laps.length,
- itemBuilder: (context, index) {
- return ListTile(
- dense: true,
- leading: CircleAvatar(
- radius: 14.r,
- backgroundColor: Colors.blue[100],
- child: Text(
- '${_laps.length - index}',
- style: TextStyle(
- fontSize: 12.sp,
- color: Colors.black87,
- ),
- ),
- ),
- title: Text(
- 'Lap ${_laps.length - index}',
- style: TextStyle(
- fontSize: 16.sp,
- ),
- ),
- trailing: Text(
- _laps[index],
- style: TextStyle(
- fontSize: 16.sp,
- fontFamily: 'monospace',
- fontWeight: FontWeight.bold,
- ),
- ),
- );
- },
- ),
- ),
- ],
- ),
- );
- }
- Widget _buildControlButton({
- required IconData icon,
- required String label,
- required VoidCallback? onPressed,
- required Color color,
- }) {
- return Column(
- children: [
- FloatingActionButton(
- onPressed: onPressed,
- backgroundColor: onPressed == null ? Colors.grey[300] : color,
- child: Icon(icon, color: Colors.white),
- ),
- SizedBox(height: 8.h),
- Text(
- label,
- style: TextStyle(
- fontSize: 14.sp,
- color: onPressed == null ? Colors.grey : Colors.black87,
- ),
- ),
- ],
- );
- }
- }
|