In this tutorial, we’ll be learning how to add interactivity to an object when I user clicks/taps on it.
This is assuming you have completed the previous tutorial on Working with Layouts in Flutter. When we get done, we’ll have learned about responding to taps, creating a custom widget, and the differences between a stateful and stateless widget.
In the previous example we have a red star icon which we are using to show if someone has liked this location. We’re going to change it to show either solid, or open, depending upon if they like it or not.
Stateful and Stateless widgets
Widgets in Flutter are either considered stateful, or stateless.
Stateless Widgets
Stateless widgets never change. Icons and Text are just two examples of stateless widgets, and actually are a subclass of the StatelessWidget class in Flutter.
Stateful Widgets
A Stateful Widget can change, like any form field you might use. They will be from a subclass called StatefulWidget in Flutter.
The Widget’s state is stored in a State object, and allows the app to remember the value when the object is redrawn during cases like rotating the screen, moving off a screen and back, etc.
When the widget’s state changes, the state object calls setState()
, telling the framework to redraw the widget.
Creating a Custom Stateful Widget
We’re going to work on creating a stateful widget that manage it’s own state. It will also not affect it’s parent.
Because it is going to manage it’s own state, it will override the createState()
method. The framework (flutter) will call createState when it wants to build a Widget.
It is also worth mentioning that when a property starts with an _ (underscore) it is considered private in Dart.
class FavoriteWidget extends StatefulWidget {
const FavoriteWidget({Key? key}) : super(key: key);
@override
_FavoriteWidgetState createState() => _FavoriteWidgetState();
}
If we write this code however, we’re going to have an issue because _FavoriteWidgetState
isn’t a class that come with Flutter, so we’ll need to create this class. Not only are we going to create it, we’re going to give some default values.
class _FavoriteWidgetState extends State<FavoriteWidget> {
bool _isFavorited = true;
int _favoriteCount = 1;
}
However, we still have an error because we are not implementing the build method. The build method will need to be overridden and is required of any Widget. This will put within the class _FavoriteWidgetState
.
@override
Widget build(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding: const EdgeInsets.all(0),
child: IconButton(
padding: const EdgeInsets.all(0),
alignment: Alignment.centerRight,
icon: (_isFavorited
? const Icon(Icons.star)
: const Icon(Icons.star_border)),
color: Colors.red[500],
onPressed: _toggleFavorite,
),
),
SizedBox(
width: 18,
child: SizedBox(
child: Text('$_favoriteCount'),
),
),
],
);
}
Notice that the icon is using the ternary operator to determine which icon should be displayed. While it is not widely used in a lot of instances, it can be used here as a simple process to determine the right icon.
Note: Placing the Text
in a SizedBox
and setting its width prevents a discernible “jump” when the text changes between the values which have a different widths. During testing, you will want to verify this, with jumps between single and double and triple digits, as well as between values with characters that might be a different width such as 1 which is thin and 2, which wider.
You will still have an error with this however, because you don’t have a _toggleFavorite
method to accept the onPressed event.
So now we will add this code:
void _toggleFavorite() {
setState(() {
if (_isFavorited) {
_favoriteCount -= 1;
_isFavorited = false;
} else {
_favoriteCount += 1;
_isFavorited = true;
}
});
}
This code is still placed in within the _FavoriteWidgetState
class as it is a method for that class and is using some of it’s internal properties.
Notice that we are updating the code simply by working with the local variables. Even on an Internet enabled app you’d probably want to do this, so you avoid unnecessary network traffic, only updating the server after a period of time, or when the user goes to leave the screen.
Implementing your new Widget
The final step will be to implement your widget. In your code, you will want to find in the titleSection
you will want to remove the icon and the text box that was there.
You will add an instance of the FavoriteWidget
creating an object so that it is created, and you get the icon and textbox back.
Testing your Custom Widget
If you have your emulator running, you should only need to do a hot reload to see this change. Save the file, and it will do the hot reload for you automatically.
I recommend testing your widget with different settings, such as going from two to three digits, or one to two digits in your text box with the number of people who have favorited. Also change whether you start with your star selected or not by default, so you can see how that changes your application.
You can make those changes by adjusting the default values of your _FavoriteWidgetState
. These are the kind of tests that you need to run for all applications, but especially mobile applications.
Adding Interactivity to Flutter Apps was originally found on Access 2 Learn
2 Comments
Comments are closed.