Flutter Tutorial
Flutter Tutorial
Docs
Development
UI
Adding interactivity
What you’ll learn
How to respond to taps.
How to create a custom widget.
The difference between stateless and stateful widgets.
How do you modify your app to make it react to user input? In this tutorial, you’ll
add interactivity to an app that contains only non-interactive widgets.
Specifically, you’ll modify an icon to make it tappable by creating a custom
stateful widget that manages two stateless widgets.
Layout tutorial showed you how to create the layout for the following screenshot.
To accomplish this, you’ll create a single custom widget that includes both the
star and the count, which are themselves widgets. Tapping the star changes state
for both widgets, so the same widget should manage both.
You can get right to touching the code in Step 2: Subclass StatefulWidget. If you
want to try different ways of managing state, skip to Managing state.
A stateless widget never changes. Icon, IconButton, and Text are examples of
stateless widgets. Stateless widgets subclass StatelessWidget.
A stateful widget is dynamic: for example, it can change its appearance in response
to events triggered by user interactions or when it receives data. Checkbox, Radio,
Slider, InkWell, Form, and TextField are examples of stateful widgets. Stateful
widgets subclass StatefulWidget.
A widget’s state is stored in a State object, separating the widget’s state from
its appearance. The state consists of values that can change, like a slider’s
current value or whether a checkbox is checked. When the widget’s state changes,
the state object calls setState(), telling the framework to redraw the widget.
Learn more about the separation of widget and state, and how state might be
managed, in Managing state.
lib/main.dart (FavoriteWidget)
content_copy
class FavoriteWidget extends StatefulWidget {
@override
_FavoriteWidgetState createState() => _FavoriteWidgetState();
}
Note: Members or classes that start with an underscore (_) are private. For more
information, see Libraries and visibility, a section in the Dart language tour.
The _toggleFavorite() method, which is called when the IconButton is pressed, calls
setState(). Calling setState() is critical, because this tells the framework that
the widget’s state has changed and that the widget should be redrawn. The function
argument to setState() toggles the UI between these two states:
layout/lakes/{step6 → interactive}/lib/main.dart
@@ -10,2 +5,2 @@
105 class MyApp extends StatelessWidget {
116 @override
@@ -38,11 +33,7 @@
3833 ],
3934 ),
4035 ),
41 - Icon(
36 + FavoriteWidget(),
42 - Icons.star,
43 - color: Colors.red[500],
44 - ),
45 - Text('41'),
4637 ],
4738 ),
4839 );
@@ -117,2 +108,2 @@
117108 );
118109 }
That’s it! When you hot reload the app, the star icon should now respond to taps.
Problems?
If you can’t get your code to run, look in your IDE for possible errors. Debugging
Flutter Apps might help. If you still can’t find the problem, check your code
against the interactive lakes example on GitHub.
lib/main.dart
pubspec.yaml
lakes.jpg
If you still have questions, refer to any one of the developer community channels.
The rest of this page covers several ways a widget’s state can be managed, and
lists other available interactive widgets.
Managing state
What's the point?
There are different approaches for managing state.
You, as the widget designer, choose which approach to use.
If in doubt, start by managing state in the parent widget.
Who manages the stateful widget’s state? The widget itself? The parent widget?
Both? Another object? The answer is… it depends. There are several valid ways to
make your widget interactive. You, as the widget designer, make the decision based
on how you expect your widget to be used. Here are the most common ways to manage
state:
If the state in question is user data, for example the checked or unchecked mode of
a checkbox, or the position of a slider, then the state is best managed by the
parent widget.
If the state in question is aesthetic, for example an animation, then the state is
best managed by the widget itself.
We’ll give examples of the different ways of managing state by creating three
simple examples: TapboxA, TapboxB, and TapboxC. The examples all work similarly—
each creates a container that, when tapped, toggles between a green or grey box.
The _active boolean determines the color: green for active or grey for inactive.
@override
_TapboxAState createState() => _TapboxAState();
}
void _handleTap() {
setState(() {
_active = !_active;
});
}
In the following example, TapboxB exports its state to its parent through a
callback. Because TapboxB doesn’t manage any state, it subclasses StatelessWidget.
@override
Widget build(BuildContext context) {
return Container(
child: TapboxB(
active: _active,
onChanged: _handleTapboxChanged,
),
);
}
}
void _handleTap() {
onChanged(!active);
}
A mix-and-match approach
For some widgets, a mix-and-match approach makes the most sense. In this scenario,
the stateful widget manages some of the state, and the parent widget manages other
aspects of the state.
In the TapboxC example, on tap down, a dark green border appears around the box. On
tap up, the border disappears and the box’s color changes. TapboxC exports its
_active state to its parent but manages its _highlight state internally. This
example has two State objects, _ParentWidgetState and _TapboxCState.
@override
Widget build(BuildContext context) {
return Container(
child: TapboxC(
active: _active,
onChanged: _handleTapboxChanged,
),
);
}
}
void _handleTapCancel() {
setState(() {
_highlight = false;
});
}
void _handleTap() {
widget.onChanged(!widget.active);
}
If you prefer, you can use GestureDetector to build interactivity into any custom
widget. You can find examples of GestureDetector in Managing state, and in the
Flutter Gallery.
When you need interactivity, it’s easiest to use one of the prefabricated widgets.
Here’s a partial list:
Standard widgets
Form
FormField
Material Components
Checkbox
DropdownButton
FlatButton
FloatingActionButton
IconButton
Radio
RaisedButton
Slider
Switch
TextField
Resources
The following resources might help when adding interactivity to your app.