A Simple Stopwatch App with Flutter

Nawfil Afif Nibir
6 min readMar 4, 2019

--

Flutter is a relatively new player in the world of code once, run everywhere frameworks. Of course, the recent hype being React Native in this genre of frameworks, Flutter has naturally been widely compared with that from pretty much its inception. While there may be pros and cons to both of these, and much enthusiasm to adopt either, to me, with my limited experience with Flutter and a bit less limited one with React Native, I can already see how much easier it is to get started with the Google’s one. I mean, the ease of getting started with a new framework depends more on the tooling and documentation available from the creators than on the ease of using the framework itself. And to that regard, Google has done a tremendously better job than Facebook. I won’t get into further details regarding this as that’s beyond the scope of this post, but as the following tutorial assumes that you already are somewhat familiar (being able to create a new Flutter project and running a Hello World app is enough) with the structure of a Flutter project, I am linking the Getting Started guide here for you to decide for yourself.

About the project

As the title mentions, the project will be a simple app containing a stopwatch. It will have the following:

  • A start/stop button
  • A reset button
  • A text field to show the elapsed time. For the sake of simplicity and keeping the tutorial short, we won’t bother too much about the user interface and some other finer details.

When we are done, the app should look like the following:

Such a pretty app!

Set the project up

I hope by now you have finished going through the Flutter basics from the link I have mentioned above, if not, this is the perfect time to do so. As you probably already know by now, there are quite a few ways to start a new Flutter project. We are going to stick to the basics and create one using the command line. The command for this is:

Let’s name our project flutter_stopwatch, so the command for this case becomes:

Configure the root of the app

The previous command creates the project and adds some default code to it in main.dart. We are not going to use this file for much more than a starting point for our app, so let's just go ahead and replace everything in it with the following code:

A few things need to be explained here,

  1. Our main code for the home view will be in another file named home.dart, we still haven't created it yet, so your editor might show an error here.
  2. We are using the green theme here.
  3. Continuing from 1, our home view in the home.dart file will be an widget named HomeWidget. This is all there is to this file for now. Next we move on to creating the home.dart file and and our home widget.

Add the home widget

Create the home.dart file and add the following code:

The code here is pretty straight forward, the only thing of note here is,

  1. The HomeWidget class will have states to maintain the various stopwatch related data, so we extend StatefulWidget,
  2. We mention a new class here, namely HomeWidgetState, as the name suggests, this should handle the states for HomeWidget.

Add the state class for the home widget

Add the following below the previous block of code:

The code here is again simple enough, the key points being,

  1. We extend State and pass HomeWidget as the type, making the resulting HomeWidgetState class ready to be used as HomeWidget's state.
  2. We set the title text for the top bar.
  3. The actual body of the home widget is set as null for now. We will add stuff to it in the next section.

Now we are ready to run our app for the first time. Run it and if everything goes well, you should be greeted with the following blank screen. Pretty eh?

Did anybody order a white canvas?

Add the buttons

We will start the actual work by adding the Start/Stop button. To do this, let’s add a new variable and a couple of methods to HomeWidgetState, so the class looks like this:

The main takeaways here,

  1. We add a variable to hold the current display text for the Start/Stop button.
  2. Body of the HomeWidgetStateis provided by the _buildBody() method now.
  3. The body is a Column widget, which will arrange the children vertically one after another in our app.
  4. We use a RaisedButton widget as our button.
  5. We use the variable added above to show the button’s title text.

Running the app now gives us the following:

Look, a button!

Not much to look at yet, but we have got our button! Now we will add a button to reset the timer similarly as the previous one. Modify the code to look like the following:

Running the app now should show the Reset button below the Start/Stop button.

Adding the stopwatch and the rest

Now that we have a base, the rest of the task is not much complicated. First we add a String to hold the timer value below _buttonText,

Then we add the Text to show this value, so the _buildBody() method becomes:

To explain the marked lines:

  1. We use an Expanded widget to make the Text widget show up at the center of the empty space below the buttons, instead of right below them. Check the Flutter documentation to know more about this widget.
  2. We use TextStyle to give the Text a font size of 72, making it nice and big.

At this point, the UI is very much how we wanted it to be. So it’s time to add the logic to make it all work. We’ll add the rest of the stuff at once and go through them one by one. The final version of the HomeWidgetState class should look like this:

The last bit to make this all work, we need to add import dart:async; at the top as the Timer class we use is part of it. Let's go through the things we have done here one by one:

  1. We add a Stopwatch object to take care of the actual stopwatch.
  2. We add a timeout to refresh the UI, and set it to 1 second interval.
  3. Calling the _startTimeout method surrounding this line starts a new Timer with the previously specified timeout interval, which upon expiry, calls the _handleTimeout method.
  4. At each timeout, we update the stopwatch text.
  5. We check if the stopwatch is running, and stop it if it is.
  6. Otherwise we start the stopwatch.
  7. If the stopwatch is running when reset is pressed, we first stop it first leveraging existing code.
  8. This is the method responsible for setting up the stopwatch text.

So we finally have our very basic stopwatch! Now to run it and make sure everything works.

Conclusion

I hope I was able to demonstrate that the ease of working with Flutter goes beyond setting it up and into the actual workflow of building great cross platform applications with it. You can download the final version from here. Please let me know if you have any feedback in the comments. Thanks for reading!

--

--