Search code examples
flutterheightstopwatch

Combining start, stop button of my stopwatch code - Flutter


I would like to combine the start stop button into one. I have broken my head trying to but still have no idea how to do so.

This app is meant for taking out the time to apply in a physics formula. This app already exists for the apple play store, but lately i have been getting a ton of feedback to combine the start and stop buttons for the stopwatch.

I have tried updating the UI to show the same button and change the text the second the user presses the start button, however i am enable to know which and what command to use to actually combine the 2 buttons.

If anybody could help i would be really grateful.

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final _isHours = true;

  final StopWatchTimer _stopWatchTimer = StopWatchTimer(
    isLapHours: true,
    onChange: (value) => print('onChange $value'),
    onChangeRawSecond: (value) => print('onChangeRawSecond $value'),
    onChangeRawMinute: (value) => print('onChangeRawMinute $value'),
  );

  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'));

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

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

  int value;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      builder: (context, child) {
        return MediaQuery(
          child: child,
          data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),
        );
      },
      debugShowCheckedModeBanner: false,
      theme: ThemeData.dark(),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Stopwatch'),
        ),
        body: Container(
          decoration: BoxDecoration(
            image: DecorationImage(
              image: AssetImage('images/wallpaper violet.png'),
              fit: BoxFit.cover,
            ),
          ),
          child: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: <Widget>[
                /// Display stop watch time
                Padding(
                  padding: const EdgeInsets.only(bottom: 0),
                  child: StreamBuilder<int>(
                    stream: _stopWatchTimer.rawTime,
                    initialData: _stopWatchTimer.rawTime.value,
                    builder: (context, snap) {
                      value = snap.data;
                      final displaytime =
                      StopWatchTimer.getDisplayTime(value, hours: _isHours);
                      return Column(
                        children: <Widget>[
                          Padding(
                            padding: const EdgeInsets.all(8),
                            child: Text(
                              displaytime,
                              style: const TextStyle(
                                fontSize: 40,
                                fontFamily: 'Poppins',
                                fontWeight: FontWeight.bold,
                                color: Colors.white,
                              ),
                            ),
                          ),
                        ],
                      );
                    },
                  ),
                ),

                Container(
                  height: 120,
                  margin: const EdgeInsets.all(8),
                  child: StreamBuilder<List<StopWatchRecord>>(
                    stream: _stopWatchTimer.records,
                    initialData: _stopWatchTimer.records.value,
                    builder: (context, snap) {
                      final value = snap.data;
                      if (value.isEmpty) {
                        return Container();
                      }
                      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: 'Poppins',
                                    fontWeight: FontWeight.bold,
                                    color: Colors.white,
                                  ),
                                ),
                              ),
                              const Divider(
                                height: 1,
                              )
                            ],
                          );
                        },
                        itemCount: value.length,
                      );
                    },
                  ),
                ),

                /// Button
                Padding(
                  padding: const EdgeInsets.all(2),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.center,
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      Padding(
                        padding: const EdgeInsets.only(bottom: 0),
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: <Widget>[
                            Padding(
                              padding:
                              const EdgeInsets.symmetric(horizontal: 4),
                              child: RaisedButton(
                                padding: const EdgeInsets.all(4),
                                color: Colors.green,
                                shape: const StadiumBorder(),
                                onPressed: () async {
                                  HapticFeedback.mediumImpact();
                                  _stopWatchTimer.onExecute
                                      .add(StopWatchExecute.start);
                                },
                                child: const Text(
                                  'Start',
                                  style: TextStyle(
                                    color: Colors.white,
                                    fontFamily: 'Poppins',
                                    fontSize: 15,
                                    fontWeight: FontWeight.bold,
                                  ),
                                ),

                              ),
                            ),
                            Padding(
                              padding:
                              const EdgeInsets.symmetric(horizontal: 4),
                              child: RaisedButton(
                                padding: const EdgeInsets.all(4),
                                color: Colors.red,
                                shape: const StadiumBorder(),
                                onPressed: () async {
                                  HapticFeedback.mediumImpact();
                                  _stopWatchTimer.onExecute
                                      .add(StopWatchExecute.lap);
                                  _stopWatchTimer.onExecute
                                      .add(StopWatchExecute.stop);
                                },
                                child: const Text(
                                  'Stop',
                                  style: TextStyle(
                                    color: Colors.white,
                                    fontFamily: 'Poppins',
                                    fontSize: 15,
                                    fontWeight: FontWeight.bold,
                                  ),
                                ),
                              ),
                            ),
                            Padding(
                              padding:
                              const EdgeInsets.symmetric(horizontal: 4),
                              child: RaisedButton(
                                padding: const EdgeInsets.all(4),
                                color: Colors.orange,
                                shape: const StadiumBorder(),
                                onPressed: () async {
                                  HapticFeedback.mediumImpact();
                                  _stopWatchTimer.onExecute
                                      .add(StopWatchExecute.reset);
                                },
                                child: const Text(
                                  'Reset',
                                  style: TextStyle(
                                    color: Colors.white,
                                    fontFamily: 'Poppins',
                                    fontSize: 15,
                                    fontWeight: FontWeight.bold,
                                  ),
                                ),
                              ),
                            ),
                          ],
                        ),
                      ),
                    ],
                  ),
                )
              ],
            ),
          ),
        ),
      ),
    );
  }
}

Solution

  • Add a bool variable _isStarted in you _MyAppState class

    class _MyAppState extends State<MyApp> {
      var _isStarted = false
    }
    

    In your Row, make a ternary condition to change your button text

    Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Padding(
          padding: EdgeInsets.symmetric(horizontal: 4),
          child: RaisedButton(
            color: _isStarted
              ? Colors.red
              : Colors.green,
            shape: StadiumBorder(),
            child: Text(
              _isStarted ? "Stop" : "Start",
              style: TextStyle(
                // Your style here
              ),
            ),
            onPressed: _isStarted
              ? () async {
                  HapticFeedback.mediumImpact();
                  _stopWatchTimer.onExecute.add(StopWatchExecute.lap);
                  _stopWatchTimer.onExecute.add(StopWatchExecute.stop);
                  setState(() {
                    _isStarted = false;
                  });
                }
              : () async {
                  HapticFeedback.mediumImpact();
                  _stopWatchTimer.onExecute.add(StopWatchExecute.start);
                  setState(() {
                    _isStarted = true;
                  });
                },
           ),
         ),
         RaisedButton(), // Your reset button here.
      ],
    )
    

    Let me know if it works.