how to implement a stopwatch timer in flutter using stop_watch_timer package?

Spread the love
implementing an stopwatch timer in flutter
implementing an stopwatch timer in flutter

how to implement a stopwatch timer in flutter using stop_watch_timer package?

Introduction:

In Flutter, a stopwatch timer can be implemented to measure the elapsed time. The stop_watch_timer package provides functionalities to easily implement a stopwatch timer. This tutorial will guide you through implementing a stopwatch timer in Flutter using the stop_watch_timer package.

Content:

Step 1. Add Dependencies:

Include the stop_watch_timer package in your pubspec.yaml file. Open the file and add the following dependency:

Save the file and run flutter pub get to fetch the package.

Step 2. Import Packages:

Import the required packages in your Dart file:


import 'package:flutter/material.dart';
import 'package:stop_watch_timer/stop_watch_timer.dart';

Step 3. Create a StopwatchTimer Instance:

Create a StopwatchTimer instance to manage the stopwatch timer. You can customize the timer with options such as format, initial value, and event listeners.


final _stopWatchTimer = StopwatchTimer(
  mode: StopWatchMode.countUp, // Stopwatch mode (count up)
  onChange: (value) => print('onChange $value'),
  onChangeRawSecond: (value) => print('onChangeRawSecond $value'),
  onEnded: () => print('onEnded'),
);

Step 4. Start, Stop, and Reset the Timer:

Use the start, stop, and reset methods to control the stopwatch timer.


_startTimer() {
  _stopWatchTimer.onExecute.add(StopWatchExecute.start);
}

_stopTimer() {
  _stopWatchTimer.onExecute.add(StopWatchExecute.stop);
}

_resetTimer() {
  _stopWatchTimer.onExecute.add(StopWatchExecute.reset);
}

Step 5. Display the Timer in the UI:

Display the stopwatch timer in your app’s UI. You can use a Text widget to show the elapsed time and buttons to control the timer


@override
Widget build(BuildContext context) {
  return MaterialApp(
    title: 'Stopwatch Timer Example',
    home: Scaffold(
      appBar: AppBar(
        title: Text('Stopwatch Timer Example'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            StreamBuilder<int>(
              stream: _stopWatchTimer.rawTime,
              initialData: _stopWatchTimer.rawTime.value,
              builder: (context, snapshot) {
                final value = snapshot.data!;
                final displayTime = StopWatchTimer.getDisplayTime(value);
                return Text(displayTime, style: TextStyle(fontSize: 48.0));
              },
            ),
            SizedBox(height: 20.0),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                ElevatedButton(
                  onPressed: _startTimer,
                  child: Text('Start'),
                ),
                SizedBox(width: 20.0),
                ElevatedButton(
                  onPressed: _stopTimer,
                  child: Text('Stop'),
                ),
                SizedBox(width: 20.0),
                ElevatedButton(
                  onPressed: _resetTimer,
                  child: Text('Reset'),
                ),
              ],
            ),
          ],
        ),
      ),
    ),
  );
}

Sample Code:


import 'package:flutter/material.dart';

import 'package:stop_watch_timer/stop_watch_timer.dart';

class MainPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        elevation: 2,
        title: Text(
          "Stop watch timer",
          style: TextStyle(fontSize: 22, color: Colors.black, fontWeight: FontWeight.w500),
        ),
        backgroundColor: Colors.blue[200],
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            Text(
              'Count Down Timer',
              style: TextStyle(fontSize: 20, color: Colors.green[700], fontWeight: FontWeight.w500),
            ),
            CountDownTimerPage(),
            SizedBox(
              height: 10,
            ),
            Container(
              height: 3,
              color: Colors.amber,
            ),
            Text(
              'Count Up Timer',
              style: TextStyle(fontSize: 20, color: Colors.green[700], fontWeight: FontWeight.w500),
            ),
            CountUpTimerPage()
          ],
        ),
      ),
    );
  }
}

class CountDownTimerPage extends StatefulWidget {
  static Future<void> navigatorPush(BuildContext context) async {
    return Navigator.of(context).push<void>(
      MaterialPageRoute(
        builder: (_) => CountDownTimerPage(),
      ),
    );
  }

  @override
  _State createState() => _State();
}

class _State extends State<CountDownTimerPage> {
  final _isHours = true;

  final StopWatchTimer _stopWatchTimer = StopWatchTimer(
    mode: StopWatchMode.countDown,
    presetMillisecond: StopWatchTimer.getMilliSecFromSecond(3),
    onChange: (value) => print('onChange $value'),
    onChangeRawSecond: (value) => print('onChangeRawSecond $value'),
    onChangeRawMinute: (value) => print('onChangeRawMinute $value'),
    onStopped: () {
      print('onStopped');
    },
    onEnded: () {
      print('onEnded');
    },
  );

  final _scrollController = ScrollController();

  @override
  void initState() {
    super.initState();
    _stopWatchTimer.rawTime.listen((value) => print('rawTime $value ${StopWatchTimer.getDisplayTime(value)}'));
    _stopWatchTimer.minuteTime.listen((value) => print('minuteTime $value'));
    _stopWatchTimer.secondTime.listen((value) => print('secondTime $value'));
    _stopWatchTimer.records.listen((value) => print('records $value'));
    _stopWatchTimer.fetchStopped.listen((value) => print('stopped from stream'));
    _stopWatchTimer.fetchEnded.listen((value) => print('ended from stream'));

    /// Can be set preset time. This case is "00:01.23".
    // _stopWatchTimer.setPresetTime(mSec: 1234);
  }

  @override
  void dispose() async {
    super.dispose();
    await _stopWatchTimer.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      crossAxisAlignment: CrossAxisAlignment.center,
      children: <Widget>[
        /// Display stop watch time
        StreamBuilder<int>(
          stream: _stopWatchTimer.rawTime,
          initialData: _stopWatchTimer.rawTime.value,
          builder: (context, snap) {
            final value = snap.data!;
            final displayTime = StopWatchTimer.getDisplayTime(value, hours: _isHours);
            return Column(
              children: <Widget>[
                Text(
                  displayTime,
                  style: const TextStyle(fontSize: 30, fontFamily: 'Helvetica', fontWeight: FontWeight.bold),
                ),
                // Padding(
                //   padding: const EdgeInsets.all(8),
                //   child: Text(
                //     value.toString(),
                //     style: const TextStyle(fontSize: 16, fontFamily: 'Helvetica', fontWeight: FontWeight.w400),
                //   ),
                // ),
              ],
            );
          },
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            StreamBuilder<int>(
              stream: _stopWatchTimer.minuteTime,
              initialData: _stopWatchTimer.minuteTime.value,
              builder: (context, snap) {
                final value = snap.data;
                print('Listen every minute. $value');
                return Column(
                  children: <Widget>[
                    Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: <Widget>[
                        const Padding(
                          padding: EdgeInsets.symmetric(horizontal: 4),
                          child: Text(
                            'minute',
                            style: TextStyle(
                              fontSize: 17,
                              fontFamily: 'Helvetica',
                            ),
                          ),
                        ),
                        Padding(
                          padding: const EdgeInsets.symmetric(horizontal: 4),
                          child: Text(
                            value.toString(),
                            style: const TextStyle(fontSize: 30, fontFamily: 'Helvetica', fontWeight: FontWeight.bold),
                          ),
                        ),
                      ],
                    ),
                  ],
                );
              },
            ),

            /// Display every second.
            StreamBuilder<int>(
              stream: _stopWatchTimer.secondTime,
              initialData: _stopWatchTimer.secondTime.value,
              builder: (context, snap) {
                final value = snap.data;
                print('Listen every second. $value');
                return Column(
                  children: <Widget>[
                    Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: <Widget>[
                        const Text(
                          'second',
                          style: TextStyle(
                            fontSize: 17,
                            fontFamily: 'Helvetica',
                          ),
                        ),
                        Padding(
                          padding: const EdgeInsets.symmetric(horizontal: 4),
                          child: Text(
                            value.toString(),
                            style: const TextStyle(
                              fontSize: 30,
                              fontFamily: 'Helvetica',
                              fontWeight: FontWeight.bold,
                            ),
                          ),
                        ),
                      ],
                    ),
                  ],
                );
              },
            ),
          ],
        ),

        /// Display every minute.

        /// Lap time.
        SizedBox(
          height: 10,
          child: StreamBuilder<List<StopWatchRecord>>(
            stream: _stopWatchTimer.records,
            initialData: _stopWatchTimer.records.value,
            builder: (context, snap) {
              final value = snap.data!;
              if (value.isEmpty) {
                return const SizedBox();
              }
              Future.delayed(const Duration(milliseconds: 100), () {
                _scrollController.animateTo(_scrollController.position.maxScrollExtent,
                    duration: const Duration(milliseconds: 200), curve: Curves.easeOut);
              });
              print('Listen records. $value');
              return ListView.builder(
                controller: _scrollController,
                scrollDirection: Axis.vertical,
                itemBuilder: (BuildContext context, int index) {
                  final data = value[index];
                  return Column(
                    children: <Widget>[
                      Padding(
                        padding: const EdgeInsets.all(8),
                        child: Text(
                          '${index + 1} ${data.displayTime}',
                          style: const TextStyle(fontSize: 17, fontFamily: 'Helvetica', fontWeight: FontWeight.bold),
                        ),
                      ),
                      const Divider(
                        height: 1,
                      )
                    ],
                  );
                },
                itemCount: value.length,
              );
            },
          ),
        ),

        /// Button
        Padding(
          padding: const EdgeInsets.only(bottom: 0),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Flexible(
                child: Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 4),
                  child: FilledButton(
                    onPressed: _stopWatchTimer.onStartTimer,
                    child: const Text(
                      'Start',
                      style: TextStyle(color: Colors.white),
                    ),
                  ),
                ),
              ),
              Flexible(
                child: Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 4),
                  child: FilledButton(
                    onPressed: _stopWatchTimer.onStopTimer,
                    child: const Text(
                      'Stop',
                      style: TextStyle(color: Colors.white),
                    ),
                  ),
                ),
              ),
              Flexible(
                child: Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 4),
                  child: FilledButton(
                    onPressed: _stopWatchTimer.onResetTimer,
                    child: const Text(
                      'Reset',
                      style: TextStyle(color: Colors.white),
                    ),
                  ),
                ),
              ),
            ],
          ),
        ),
        Padding(
          padding: const EdgeInsets.symmetric(horizontal: 4),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Flexible(
                child: Padding(
                  padding: const EdgeInsets.all(0).copyWith(right: 8),
                  child: FilledButton(
                    onPressed: _stopWatchTimer.onAddLap,
                    child: const Text(
                      'Lap',
                      style: TextStyle(color: Colors.white),
                    ),
                  ),
                ),
              ),
            ],
          ),
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Flexible(
              child: Padding(
                padding: const EdgeInsets.symmetric(horizontal: 4),
                child: FilledButton(
                  onPressed: () {
                    _stopWatchTimer.setPresetHoursTime(1);
                  },
                  child: const Text(
                    'Set Hours',
                    style: TextStyle(color: Colors.white),
                  ),
                ),
              ),
            ),
            Flexible(
              child: Padding(
                padding: const EdgeInsets.symmetric(horizontal: 4),
                child: FilledButton(
                  onPressed: () {
                    _stopWatchTimer.setPresetMinuteTime(59);
                  },
                  child: const Text(
                    'Set Minute',
                    style: TextStyle(color: Colors.white),
                  ),
                ),
              ),
            ),
          ],
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Flexible(
              child: Padding(
                padding: const EdgeInsets.symmetric(horizontal: 4),
                child: FilledButton(
                  onPressed: () {
                    _stopWatchTimer.setPresetSecondTime(10);
                  },
                  child: const Text(
                    'Set +Second',
                    style: TextStyle(color: Colors.white),
                  ),
                ),
              ),
            ),
            Flexible(
              child: Padding(
                padding: const EdgeInsets.symmetric(horizontal: 4),
                child: FilledButton(
                  onPressed: () {
                    _stopWatchTimer.setPresetSecondTime(-10);
                  },
                  child: const Text(
                    'Set -Second',
                    style: TextStyle(color: Colors.white),
                  ),
                ),
              ),
            ),
          ],
        ),
        Padding(
          padding: const EdgeInsets.symmetric(horizontal: 4),
          child: FilledButton(
            onPressed: _stopWatchTimer.clearPresetTime,
            child: const Text(
              'Clear PresetTime',
              style: TextStyle(color: Colors.white),
            ),
          ),
        ),
      ],
    );
  }
}

class CountUpTimerPage extends StatefulWidget {
  static Future<void> navigatorPush(BuildContext context) async {
    return Navigator.push<void>(
      context,
      MaterialPageRoute(
        builder: (_) => CountUpTimerPage(),
      ),
    );
  }

  @override
  _Statee createState() => _Statee();
}

class _Statee extends State<CountUpTimerPage> {
  final _isHours = true;

  final StopWatchTimer _stopWatchTimer = StopWatchTimer(
    mode: StopWatchMode.countUp,
    onChange: (value) => print('onChange $value'),
    onChangeRawSecond: (value) => print('onChangeRawSecond $value'),
    onChangeRawMinute: (value) => print('onChangeRawMinute $value'),
    onStopped: () {
      print('onStop');
    },
    onEnded: () {
      print('onEnded');
    },
  );

  final _scrollController = ScrollController();

  @override
  void initState() {
    super.initState();
    _stopWatchTimer.rawTime.listen((value) => print('rawTime $value ${StopWatchTimer.getDisplayTime(value)}'));
    _stopWatchTimer.minuteTime.listen((value) => print('minuteTime $value'));
    _stopWatchTimer.secondTime.listen((value) => print('secondTime $value'));
    _stopWatchTimer.records.listen((value) => print('records $value'));
    _stopWatchTimer.fetchStopped.listen((value) => print('stopped from stream'));
    _stopWatchTimer.fetchEnded.listen((value) => print('ended from stream'));

    /// Can be set preset time. This case is "00:01.23".
    // _stopWatchTimer.setPresetTime(mSec: 1234);
  }

  @override
  void dispose() async {
    super.dispose();
    await _stopWatchTimer.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      crossAxisAlignment: CrossAxisAlignment.center,
      children: <Widget>[
        /// Display stop watch time
        StreamBuilder<int>(
          stream: _stopWatchTimer.rawTime,
          initialData: _stopWatchTimer.rawTime.value,
          builder: (context, snap) {
            final value = snap.data!;
            final displayTime = StopWatchTimer.getDisplayTime(value, hours: _isHours);
            return Column(
              children: <Widget>[
                Text(
                  displayTime,
                  style: const TextStyle(fontSize: 30, fontFamily: 'Helvetica', fontWeight: FontWeight.bold),
                ),
                // Text(
                //   value.toString(),
                //   style: const TextStyle(fontSize: 16, fontFamily: 'Helvetica', fontWeight: FontWeight.w400),
                // ),
              ],
            );
          },
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            StreamBuilder<int>(
              stream: _stopWatchTimer.minuteTime,
              initialData: _stopWatchTimer.minuteTime.value,
              builder: (context, snap) {
                final value = snap.data;
                print('Listen every minute. $value');
                return Column(
                  children: <Widget>[
                    Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: <Widget>[
                        const Padding(
                          padding: EdgeInsets.symmetric(horizontal: 4),
                          child: Text(
                            'minute',
                            style: TextStyle(
                              fontSize: 17,
                              fontFamily: 'Helvetica',
                            ),
                          ),
                        ),
                        Padding(
                          padding: const EdgeInsets.symmetric(horizontal: 4),
                          child: Text(
                            value.toString(),
                            style: const TextStyle(fontSize: 30, fontFamily: 'Helvetica', fontWeight: FontWeight.bold),
                          ),
                        ),
                      ],
                    ),
                  ],
                );
              },
            ),

            /// Display every second.
            StreamBuilder<int>(
              stream: _stopWatchTimer.secondTime,
              initialData: _stopWatchTimer.secondTime.value,
              builder: (context, snap) {
                final value = snap.data;
                print('Listen every second. $value');
                return Column(
                  children: <Widget>[
                    Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: <Widget>[
                        const Padding(
                          padding: EdgeInsets.symmetric(horizontal: 4),
                          child: Text(
                            'second',
                            style: TextStyle(
                              fontSize: 17,
                              fontFamily: 'Helvetica',
                            ),
                          ),
                        ),
                        Text(
                          value.toString(),
                          style: const TextStyle(
                            fontSize: 30,
                            fontFamily: 'Helvetica',
                            fontWeight: FontWeight.bold,
                          ),
                        ),
                      ],
                    ),
                  ],
                );
              },
            ),
          ],
        ),

        /// Display every minute.

        /// Lap time.
        SizedBox(
          height: 20,
          child: StreamBuilder<List<StopWatchRecord>>(
            stream: _stopWatchTimer.records,
            initialData: _stopWatchTimer.records.value,
            builder: (context, snap) {
              final value = snap.data!;
              if (value.isEmpty) {
                return const SizedBox.shrink();
              }
              Future.delayed(const Duration(milliseconds: 100), () {
                _scrollController.animateTo(_scrollController.position.maxScrollExtent,
                    duration: const Duration(milliseconds: 200), curve: Curves.easeOut);
              });
              print('Listen records. $value');
              return ListView.builder(
                controller: _scrollController,
                scrollDirection: Axis.vertical,
                itemBuilder: (BuildContext context, int index) {
                  final data = value[index];
                  return Column(
                    children: <Widget>[
                      Padding(
                        padding: const EdgeInsets.all(8),
                        child: Text(
                          '${index + 1} ${data.displayTime}',
                          style: const TextStyle(fontSize: 17, fontFamily: 'Helvetica', fontWeight: FontWeight.bold),
                        ),
                      ),
                      const Divider(
                        height: 1,
                      )
                    ],
                  );
                },
                itemCount: value.length,
              );
            },
          ),
        ),

        /// Button
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Flexible(
              child: Padding(
                padding: const EdgeInsets.symmetric(horizontal: 4),
                child: FilledButton(
                  onPressed: _stopWatchTimer.onStartTimer,
                  child: const Text(
                    'Start',
                  ),
                ),
              ),
            ),
            Flexible(
              child: Padding(
                padding: const EdgeInsets.symmetric(horizontal: 4),
                child: FilledButton(
                  onPressed: _stopWatchTimer.onStopTimer,
                  child: const Text(
                    'Stop',
                  ),
                ),
              ),
            ),
            Flexible(
              child: Padding(
                padding: const EdgeInsets.symmetric(horizontal: 4),
                child: FilledButton(
                  onPressed: _stopWatchTimer.onResetTimer,
                  child: const Text(
                    'Reset',
                  ),
                ),
              ),
            ),
          ],
        ),
        Padding(
          padding: const EdgeInsets.symmetric(horizontal: 4),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Flexible(
                child: Padding(
                  padding: const EdgeInsets.all(0).copyWith(right: 8),
                  child: FilledButton(
                    onPressed: _stopWatchTimer.onAddLap,
                    child: const Text(
                      'Lap',
                    ),
                  ),
                ),
              ),
            ],
          ),
        ),
        Padding(
          padding: const EdgeInsets.all(0),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Flexible(
                child: Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 4),
                  child: FilledButton(
                    onPressed: () {
                      _stopWatchTimer.setPresetHoursTime(1);
                    },
                    child: const Text(
                      'Set Hours',
                    ),
                  ),
                ),
              ),
              Flexible(
                child: Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 4),
                  child: FilledButton(
                    onPressed: () {
                      _stopWatchTimer.setPresetMinuteTime(59);
                    },
                    child: const Text(
                      'Set Minute',
                    ),
                  ),
                ),
              ),
            ],
          ),
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Flexible(
              child: Padding(
                padding: const EdgeInsets.symmetric(horizontal: 4),
                child: FilledButton(
                  onPressed: () {
                    _stopWatchTimer.setPresetSecondTime(10);
                  },
                  child: const Text(
                    'Set +Second',
                  ),
                ),
              ),
            ),
            Flexible(
              child: Padding(
                padding: const EdgeInsets.symmetric(horizontal: 4),
                child: FilledButton(
                  onPressed: () {
                    _stopWatchTimer.setPresetSecondTime(-10);
                  },
                  child: const Text(
                    'Set -Second',
                  ),
                ),
              ),
            ),
          ],
        ),
        Padding(
          padding: const EdgeInsets.symmetric(horizontal: 4),
          child: FilledButton(
            onPressed: _stopWatchTimer.clearPresetTime,
            child: const Text(
              'Clear PresetTime',
            ),
          ),
        ),
      ],
    );
  }
}

Output:

implementing an stopwatch timer in flutter
implementing an stopwatch timer in flutter

Conclusion:

By following these steps, you can easily implement a stopwatch timer in Flutter using the stop_watch_timer package. Use this stopwatch timer to measure elapsed time in your Flutter apps.

 

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *