All things Flutter — How I built my first Flutter app!

Flutter

So…you must have heard about ‘Flutter’ — a brand new SDK developed by Google themselves!

There was a lot of hype surrounding it as developers all around the world waited for the beta release with bated breath. Long story short, Flutter allows you to build cross-platform apps using the Dart language (Google’s own) and aims to speed up ‘Development cycles’. As with every developer(self-styled as I am only a student), I couldn’t contain my excitement and I immediately dived into the docs. From my experience, the Dart language appears to be a blend of Object-Oriented languages(like Java) and scripting languages(like JavaScript) which makes it intuitive and quite easy for people from both backgrounds’ to pick it up. Another great feature that Flutter offers is the stateful ‘Hot reload’ — Changes in code are reflected almost instantaneously while the app is running — and you can watch the changes live. This in my opinion will accelerate app development and maximize productivity (Think about all the time saved!). There is tons of information in the official docs so be sure to check it out!

Also, I came across an amazing Medium post that provides a comprehensive analysis of the Dart language and its merits in Flutter, you can find it here.


In this post I discuss how I convert a simple(almost trivial) android app — A BasketBall score keeper — into a Flutter app. Before continuing reading I suggest you go through the documentation and familiarize yourself with words like ‘stateless’, ‘stateful widget’ etc.

This is what the finished app looks like.

Track the scores!

So let’s get right into it!

Step 1 — Building the Layout

We will start by creating a new Flutter project, I used Android Studio IDE for my project. You can use anything either the IntelliJ IDE or any good text editor with the flutter plugins installed. If you are facing any trouble setting up your project, you can refer this link.

After successfully creating the project you will be directed to this file — main.dart, which is the entry point for your flutter app and it’s where most of the code lives. It already contains some basic code and we can start by directly modifying it!

Go to _MyHomePageState class and delete everything under it. Most of our app logic is contained within this class. If you didn’t already know, everything in flutter is based on widgets — stateless and stateful. The _MyHomePage class extends the stateful widget which is required for maintaining state and adding interactivity to your app. You can read about it more over here.

Alright so let’s create a function that will create the column for the teams. You could create two separate columns but I love sticking to the ‘DRY’ principle and prefer to keep everything modular.

Column scoreButtonColumn(String label, ) {
return new Column(
// Column is also layout widget. It takes a list of children and
// arranges them vertically. By default, it sizes itself to fit its
// children horizontally, and tries to be as tall as its parent.
//
// Invoke "debug paint" (press "p" in the console where you ran
// "flutter run", or select "Toggle Debug Paint" from the Flutter tool
// window in IntelliJ) to see the wireframe for each widget.
//
// Column has various properties to control how it sizes itself and
// how it positions its children. Here we use mainAxisAlignment to
// center the children vertically; the main axis here is the vertical
// axis because Columns are vertical (the cross axis would be
// horizontal).
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[new Container(
margin: const EdgeInsets.only(bottom: 16.0),
child: new Text(
label,
style: new TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.bold,
),
),
),
new Container(
padding: const EdgeInsets.all(8.0),
child: new Text(
(label=='Team A')?'$_counterA':'$_counterB',
style: new TextStyle(
fontSize: 32.0,
color: Colors.black38
),

),
),
new Container(
padding: const EdgeInsets.all(8.0),
child: new RaisedButton(
child: new Text('+3'),
onPressed: (label == 'Team A')?_incrementByThreeCounterA:_incrementByThreeCounterB,
),
),

new Container(
padding: const EdgeInsets.all(8.0),
child: new RaisedButton(
child: new Text('+2'),
onPressed: (label == 'Team A')?_incrementByTwoCounterA:_incrementByTwoCounterB,
),
),
new Container(
padding: const EdgeInsets.all(8.0),
child: new RaisedButton(
child: new Text('free throw'),
onPressed: (label == 'Team A')?_incrementCounterA:_incrementCounterB,
),
),

],
);
}

Note: If the code formatting gets skewed on copy-paste, you can right-click anywhere inside the file and click ‘Reformat code with dartfmt’ option.

Each button in the layout has a ‘onPressed’ property to which we have assigned the respective methods. The code might be showing a few warnings and errors but don’t worry it will get resolved soon!

We use the canvas class for drawing shapes and we will be using it to draw the vertical line. I was stuck on this for some time but after much digging I got it!

Add the following piece of code outside of all the classes:

class Sky extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
canvas.drawRect(
new Rect.fromLTRB(
0.0, -100.0, 1.0, 150.0
),
new Paint()..color = new Color(0xFF0099FF),
);
}

@override
bool shouldRepaint(Sky oldDelegate) {
return false;
}
}

It adds a blue line, you can change the color or make use of themes to suit your needs.

Step 2 — Adding Interactivity

Here’s where we define the counter variables and the respective methods that get called on clicking the buttons. Under _MyHomePageState class add the following lines of code:

int _counterA = 0;
int _counterB = 0;

void _incrementCounterA() {
setState(() {
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counterA++;
});
}
void _incrementByTwoCounterA() {
setState((){
_counterA+=2;
});
}

void _incrementByThreeCounterA(){
setState((){
_counterA+=3;
});
}
void _incrementCounterB() {
setState(() {
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counterB++;
});
}
void _incrementByTwoCounterB() {
setState((){
_counterB+=2;
});
}

void _incrementByThreeCounterB(){
setState((){
_counterB+=3;
});
}

void _resetScore(){
setState((){
_counterA = 0;
_counterB = 0;
});
}

There are two counter variables being maintained for Team A and Team B. On clicking the reset button the values for both the variables are turned to zero.

The ‘setState()’ method is of importance — it informs the framework of the changes made in state, in our case the counter variables, and redraws the widgets on the screen.

Step 3 — Putting everything together!

Now that we have our UI complete and we have also handled interactivity, all that remains is to put everything together in _MyHomePageState’s build method. This method builds and returns the widget to be drawn on the screen.

Here’s the code:

@override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.

return new Scaffold(
appBar: new AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: new Text(widget.title),
),
body: new Container(
child: new Column(
children: <Widget>[
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
scoreButtonColumn('Team A'),
new Container(
margin: const EdgeInsets.only(left: 16.0, right: 16.0),
child: new CustomPaint(
painter: new Sky(),
),
),
scoreButtonColumn('Team B'),
],
),
new Container(
margin: const EdgeInsets.only(top: 72.0),
child: new RaisedButton(
onPressed: _resetScore,
child: new Text('Reset'),
),
)
],
),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}

And we are done! Here’s the app in action:

Score Keeper!

It was a fun experience for me to code this simple app! I hope you had fun reading this and maybe you learned a thing or two. Flutter has just arrived and it is definitely here to stay! There’s so much more to learn and explore, and I hope to write more such posts. If you liked this, please follow this space closely. As always, happy coding :)

Like what you read? Give Abdul Kadir a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.