Flutter: Magic 8 Ball Project

Nicholas An
4 min readSep 30, 2020

--

Magic-8-Ball was chosen as the first story of Flutter series because the prior assignments/projects have been a bit insufficient in terms of giving lots of useful details. So let’s take a look at the source code.

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

void main() => runApp(
MaterialApp(
home: BallPage(),
),
);

class BallPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.blue[900],
title: Text("Ask Me Anything"),
),
body: Ball(),
backgroundColor: Colors.blue,
);
}
}

class Ball extends StatefulWidget {
@override
_BallState createState() => _BallState();
}

class _BallState extends State<Ball> {
int ballNumber = 1;
@override
Widget build(BuildContext context) {
return Center(
child: FlatButton(
onPressed: () {
setState(() {
ballNumber = Random().nextInt(4) + 1;
});
},
child: Image.asset("images/ball$ballNumber.png"),
),
);
}
}

Step 1 — Set up

First, I downloaded a skeleton project from appbrewery’s git repo. The skeleton code looks like this:

import 'package:flutter/material.dart'; void main() => runApp(      
MaterialApp(
home: null,
),
);

Quite nothing there except the MaterialApp, which is the foundation for pretty much everything. MaterialApps are important foundations because they are what the Google developer had in mind to give us some sort of a sketchbook for app development.

Step 2 — Create a Stateless Widget

This one is easy. All I had to do was to type ‘stless’ somewhere in the main.dart file and autocomplete the rest of a stateless widget code. The name of the stateless widget was BallPage. Then, in the MaterialApp, you can see that the property ‘home’ has the value of ‘null’. I changed that null value to BallPage so that this stateless widget would now become the home of this MaterialApp.

The next part of this step is some colorings. Let’s take a look at the finished statelesswidget part of the code.

class BallPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container();
}
}

You can see that inside the build method, it returns just a Container. Let’s fix that and add an AppBar(which has a backgroundColor and a title) and body(which has a Container for now) and its own backgroundColor.

class BallPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.blue[900],
title: Text("Ask Me Anything"),
),
body: Container(),
backgroundColor: Colors.blue,
);
}
}

Here is a diagram.

Cool stuff. Moving on.

Step 3 — Create a Stateful Widget

Just like how I created the stateless one, I used the shortcut for this, “stful”. Take a look at the default autocompletion.

class Ball extends StatefulWidget {
@override
_State createState() => _State();
}

class _State extends State<> {
@override
Widget build(BuildContext context) {
return Container();
}
}

Remember the Container for the body of the stateless widget? It’s time to change that.

class BallPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.blue[900],
title: Text("Ask Me Anything"),
),
body: Ball(),
backgroundColor: Colors.blue,
);
}
}

Now, BallPage will have the Ball stateful widget as its body. Let’s go to the Ball stateful widget and make it centered, and give it a FlatButton. Let’s also make this FlatButton an image of an 8-Ball.

class Ball extends StatefulWidget {
@override
_BallState createState() => _BallState();
}

class _BallState extends State<Ball> {
int ballNumber = 1;
@override
Widget build(BuildContext context) {
return Center(
child: FlatButton(
child: Image.asset("images/ball1.png"),
),
);
}
}

Step 4 — Make it Interactive

Inside the FlatButton, you need “onPressed: () {}” inside of which should also have something that alters some state… something like “setState (() {});”

class _BallState extends State<Ball> {
@override
Widget build(BuildContext context) {
return Center(
child: FlatButton(
onPressed: () {
setState(() {

});
},
child: Image.asset("images/ball1.png"),
),
);
}
}

Step 5 — Randomise it

It’s time to import the math library.

import 'dart:math';

Then use it. Before implementing this random number generator, create a variable to apply this random number to the file path. Let’s call it ‘ballNumber’ and place it outside of the build method so the variable does not generate every time the build method is called.

class Ball extends StatefulWidget {
@override
_BallState createState() => _BallState();
}

class _BallState extends State<Ball> {
int ballNumber = 1;
@override
Widget build(BuildContext context) {
return Center(
child: FlatButton(
onPressed: () {
setState(() {
ballNumber = Random().nextInt(4) + 1;
});
},
child: Image.asset("images/ball$ballNumber.png"),
),
);
}
}

This is it! The project is now finished.

--

--

Nicholas An
Nicholas An

Written by Nicholas An

Backend Server Developer in South Korea

No responses yet