First, I want to start by creating a clear picture of what we want to achieve. I work currently on a Scrum Team, we always have to carry around our cards for sprint poker. These cards are old, dirty and very often used from a lot of teams and so I decided to change that with an app, once and for all.

Scrum Poker App

If you have never worked in a Scrum Team before, you maybe never heard the term Scrum Poker. To explain the whole idea, would probably be too much for that story, but if you are interested Ravindra Prasad wrote an excellent article about that topic.

It is like real poker, but everyone has the same cards. - Max Weber

Visual guidance

For me, it is always helpful in my projects to have visual guidance like a prototype. This prototype can be a drawing on a paper or a fully-fledged prototype. For this article, I created a quick prototype in Adobe XD just to show you how it can look like and to give myself visual support.

Scrum Poker App Solution -
Gif

With that, we have a prototype and now we know what we want to create. Now we are ready for development. First of all, we have to create a new project with Flutter. On the Flutter Website, there are more information on how to set up your environment. I will use for this story Android Studio with the Flutter and Dart plugin.

Restructure our boilerplate

After the setup of the flutter project, let us start with removing all the comments that we do not need. I separate the Home Page from the main file so that we have a better feeling for our application. With that, we bring a bit more order in the project boilerplate. In our main file, this is what should remain.


import 'package:flutter/material.dart';

import 'package:flutter_scrum_cards/pages/myHomePage.dart';


void main() => runApp(MyApp());


class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

In the “myHomePage.dart” you will find the Stateful “MyHomePage” Widget that is initialized with the flutter project.

My Homepage Dart
File

And the following image represents the folder structure:

Folder structure of our Flutter
project

Our HomePage

For our first shot, we want to use the existing Scaffold of the HomePage. This contains our scrum cards and a Flutter GridView. The GridView gives us the option to align multiple items in a grid. The count constructor of the GridView provides us, with the out-of-the-box functionality, to create our Grid with Cards.

Homepage Second
Step

First, we initialize a variable “Fibonacci” so that we can contain the numbers in an array. If you take a closer look into the children of the count constructor of the GridView you can see the “for Loop”. Is this not great? We can loop inside the children array to map our Fibonacci array to placeholders.

Placeholders for our scrum card
app

Great, the Grid looks already very promising. Did you see how the Placeholder widget is handy in this part? With that in place, we do not have to create anything for the card just yet. However, the result is already evident. The Placeholders help us to structure already our app without actually implementing something.

The Cards

Now that we have the basic structure in place, we have to think about how we want to display our Cards. Thankfully Flutter provides already something for us. The Card Widget will help us to create excellent visualization of the cards with Text inserted. Because the cards will not change, we can create a stateless widget for it with an icon or a number. For now, it will live in the “MyHomePage”.

ScrumCard Build
Function

ScrumCard Grid
View

ScrumCard
App

Gestures

Now it is time to control our behaviour of the app. When we tap a card, it should remove the widgets from the tree and replace it with a single card widget. That, however, changes the state of the “MyHomePage” Widget.

To achieve that tap behaviour, we first have to surround our Card element with a GestureController. After that, we have to specify the onTap event inside of the card.

ScrumCard
Widget

This will now print every click on a card in a separate line in the console.

ScrumCard Visible Press
Events

Downtime

Alright, we made it very far already. So let’s take a break and recap shortly, what we created already.

a Design for our Scrum Card App

a HomePage

a ScrumCard widget

Gestures and tapping event

The next thing that we need to do is to change the state of our app, after a tap. Whenever a card is tapped we want to replace the Body from the HomePage with a Big ScrumCard Widget.

Now comes the tough part so. Therefore make yourself ready, take a deep breath and then let’s get into it!

State Management

There are two different kinds of Widgets in Flutter.

Stateless Widgets

Stateful Widgets

The stateless widget is a widget that will always be shown according to its initial values. During its lifetime the initial values can not change. The stateful widget, on the other hand, contains a real state and if you change the state the widget will be re-rendered. If you want to read more about the different types of widgets feel free to take a look at the article by Deepak K.

Now we have to first time handle the state of our widgets. When we click the button the state of the “Grid Widget” should change to a big “Card Widget”. This tells us that we have at least two different states in our app. To keep track of these states we have to change our current “Stateless” Widget to a “Stateful” Widget. The easiest way is to click on Stateless Widget and use the IDE function to change the Stateless Widget to a Stateful Widget.

Switch in IntelliJ to a Stateful
Widget

Because the new Widget is now stateful, we can change its value and the “build” method can react to these different states.

States are not
contained

We want to track the information of the Icon that we want to show or the Text that is visible on the card so we need that to a state. I call that variables “singleCardText” and “singleCardIcon”. Additionally, I want to have a boolean that knows if I have to show the Main Page with all Cards or just the Single Big Card.

Be careful at that point, I made here a big mistake and put all these variables in the build method. The build method gets called multiple times and whenever it gets called it overwrites the values again. Of course, that sounds trivial but cost me 1 hour of my lifetime.

The Exchange

Now we want to swap the widgets based on the “isHomePage” value. Therefore, we can use one of Flutter skills. We surround our GridView.count constructor with a ternary operator. That checks our isHomePage and add the respective Widget to the Container.

Ternery
Operators

If you get confused by the “?” and the “:” in the code I can recommend you to read an article about “Ternary Operator” from Deven Joshi. With that in place, we have the opportunity to change the “isHomePage” to false and it would show us only the Padding (and whatever is there inside) or we keep it on true, and it will show us the GridView. Therefore we need the “setState” method. It will allow us very easy to change the current state of the widget.

SwitchToCard method and
State

Great so far. Now instead of the tap where we just print something in the console, we want to execute the “switchToCard” method. But how? The method has to live in the _HomePageState and the ScrumCard has no access to that state? Alright then, let me explain it to you because there is a fairly simple solution to that problem. We just pass our function into the ScrumCard Widget. And whenever the user taps now on the card we call that method and “notify” our parent widget.

Showcase of the notifyParent
method

Showcase of the notifyParent method
(2)

If you take a brief look into the code snippets you can see that the ScrumCard calls the notifyParent method, which in fact is the switchToCard method. This should help us now to transform from a grid with multiple scrum cards, to a single big one and Vice Versa. Now there is only one step left, we have to create a beautiful Card UI that will be generated when the isHomePage is false.

Finished ScrumCard Widget with
Padding

As you most likely already discovered I added here another function for notifyParent so that we can swap back to the HomePage.

Now the switch of card and grid should work already. To improve our app even more we can use the “AnimatedSwitcher”. I found this amazing video from the flutter team and that is a perfect use case. The AnimatedSwitcher, as you maybe have already guessed, helps us to swap two widgets with each other. It adds a smooth transition between these two and this looks much more friendly. You just have to put your ternary operator in between as a child and give it a Duration how long the transition should take.

Added
AnimatedSwitcher

Ok, so let’s run our simulator or emulator and take a look how the app looks now.

Final Result
Showcase

Conclusion and What’s next

This is now an app that already solves one important problem in software engineering. From now on I do not have any more to carry real cards from one room to another. Never again I will have to grab old smelly cards and show them to my Product Owner. We do not want to know which liquids touched those filthy cards…

This is of course just the beginning. With the knowledge that we got during this session, we can do much more. This app shows how easy it is with flutter to create a nice fully functional app.

Now it is your turn. My challenge for you till my next article is, to create this app or fork my repository from GitHub and extend this app by a small additional functionality. To give you some examples that you could add,

  • Make it possible to change from Fibonacci numbers to other Scrum Poker numbers

  • Create a history of the selected cards

  • Make a custom Animation between the transitions

And if you are finished spread the word and let everyone know how cool Flutter and our community is! I am already curious to see all the beautiful results. If you have any feedback let me know and if you are interested in other cool articles, feel free to follow me on Twitter or take a look into my GitHub Repository.

Thank you for reading, stay curious and if you have time consider supporting me on Patreon.