Programming Flutter: Extracted From
Programming Flutter: Extracted From
Programming Flutter: Extracted From
Programming Flutter
Native, Cross-Platform Apps the Easy Way
This PDF file contains pages extracted from Programming Flutter, published by
the Pragmatic Bookshelf. For more information or to purchase a paperback or
PDF copy, please visit http://www.pragprog.com.
Note: This extract contains some colored text (particularly in code listing). This
is available only in online versions of the books. The printed versions are black
and white. Pagination might vary between the online and printed versions; the
content is otherwise identical.
Copyright © 2020 The Pragmatic Programmers, LLC.
Carmine Zaccagnino
All rights reserved. No part of this publication may be reproduced, stored in a retrieval system,
or transmitted, in any form, or by any means, electronic, mechanical, photocopying, recording,
or otherwise, without the prior consent of the publisher.
ISBN-13: 978-1-68050-695-2
Encoded using the finest acid-free high-entropy binary digits.
Book version: P1.0—February 2020
Give the App Your Personal Touch
Now let’s modify what we’ve seen. We’ll change the app color to be green, add
a red reset button to reset the counter to 0, make the app display the string
“None” instead of the counter when the counter is at 0 and change the appBar’s
title text. In doing this, we’ll get a feel for how to make simple changes, and
also an introduction to more complex Flutter syntax.
Go ahead and change Colors.blue to Colors.green so that those lines instead read
as follows:
firstapp/lib/main.dart
theme: ThemeData(
primarySwatch: Colors.green,
),
After we’ve done that, we need to set this variable to “None” if the counter is
0 and to a string representation of the counter if that isn’t the case. We’re
going to need a conditional.
add:
firstapp/lib/main.dart
if(_counter == 0) {
_displayedString = "None";
} else {
_displayedString = _counter.toString();
}
This is a simple if-else construct and, like in many other languages, it could
also be expressed in a braceless way as:
if(_counter == 0) _displayedString = "None";
else _displayedString = _counter.toString();
You can find more information about conditional constructs and expressions
in Conditional Constructs and Expressions, on page ?.
You might have noticed the syntax currently used to display the counter to
the user:
'$_counter'
The single quotes (unlike in C, C++, and Java, single and double quotes are
the same in Dart) enclose a string literal, and inside this string literal is a
variable name (_counter) preceded by a dollar sign.
This is how string literals work in Dart: they are enclosed in single or double
quotes. And we can include variables in string literals by preceding the variable
name with a dollar sign.
You can find more information about string literals and string interpolation
in Characters and Strings, on page ?.
Back to our example. Since we now want to display a string, we can replace:
'$_counter'
to be just:
displayedString
We will use a fixed string defined in the app’s constructor and a variable part,
which will be created inside the build method.
The fixed part is the title we give to MyHomePage’s constructor (and which then
becomes widget.title), which will be “An app that can count to”:
firstapp_starting/lib/main.dart
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
Now we need to edit _MyHomePageState’s build method again, since that’s what
gets called every time the app’s state changes, and that’s where the variable
part of the string will have to be generated.
and change:
widget.title
to:
'${widget.title} $_counter'
As you can see, we’ve done the opposite of what we did to the counter, and
we had to use braces for widget.title because dot notation was needed to access
a member variable.
Before we add the button itself, let’s define a simple method that changes the
state and resets the counter to 0.
The FlatButton is ideal when you want a button that displays text: it has a child
attribute that is usually a Text widget, but you have the option to set it to
anything.
The reason why the FlatButton is used mostly for text buttons is that using an
IconButton exists specifically for the creation of icon-based buttons, by allowing
the developer to specify an Icon object as its icon attribute, with the button only
consisting of the icon and a small amount of padding.
One of the attributes that show the difference in focus is that the FlatButton’s
color attribute controls the color of the button itself (the background to its
content), whereas the IconButton’s color attribute control’s the icon’s color.
To add the button, locate the following lines in _MyHomePageState’s build method:
firstapp_starting/lib/main.dart
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
and add, inside the square brackets, the following to the list of widgets:
firstapp/lib/main.dart
FlatButton(
onPressed: _resetCounter,
color: Colors.red,
child: Text(
"Reset counter",
style: Theme.of(context).textTheme.button,
),
),
First of all, the action we want to perform is to fire the _resetCounter function,
so we set that as the onPressed attribute.
The FlatButton’s color attribute should not be confused with the CSS attribute
that goes by the same name: as I described earlier, it changes the button’s
background color, not the text color, which we’ll leave black.
The child attribute is just a text string with the built-in button text theme.
@override
_MyHomePageState createState() => _MyHomePageState();
}
void _incrementCounter() {
setState(() {
_counter++;
});
}
void _resetCounter() {
setState(() {
_counter = 0;
});
}
@override
Widget build(BuildContext context) {
if(_counter == 0) {
_displayedString = "None";
} else {
_displayedString = _counter.toString();
}
return Scaffold(
appBar: AppBar(
title: Text('${widget.title} $_counter'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
_displayedString,
style: Theme.of(context).textTheme.display1,
),
FlatButton(
onPressed: _resetCounter,
color: Colors.red,
child: Text(
"Reset counter",
style: Theme.of(context).textTheme.button,
),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
Now, build and run or reload the app and the result will be the same as the
screenshots we saw earlier.