Handling user input
- Introduction to handling user input
- Buttons
- Text
- Select a value from a group of options
- Toggle between values
- Select a date or time
- Swipe & slide
- Looking for more widgets?
- Build interactive widgets with GestureDetector
- Testing
- Next: Networking
- Feedback
Now that you know how to manage state in your Flutter app, how can you let users interact with your app and change its state?
Introduction to handling user input
#As a multi-platform UI framework, there are many different ways for users to interact with a Flutter app. The resources in this section introduce you to some of the common widgets used for enabling user interaction within your app.
Some user input mechanisms, like scrolling, have already been covered in Layouts.
widget catalog has an inventory of commonly used widgets in the Material and Cupertino libraries.
Reference: The
Next, we'll cover a few of the Material widgets that support common use cases for handling user input in your Flutter app.
Buttons
#Buttons allow a user to initiate an action in the UI by clicking or tapping. The Material library provides a variety of button types that are functionally similar, but styled differently for various use cases, including:
ElevatedButton
: A button with some depth. Use elevated buttons to add dimension to otherwise mostly flat layouts.FilledButton
: A filled button that should be used for important, final actions that complete a flow, like Save, Join now, or Confirm.Tonal Button
: A middle ground button betweenFilledButton
andOutlinedButton
. They're useful in contexts where a lower-priority button requires more emphasis than an outline, like Next.OutlinedButton
: A button with text and a visible border. These buttons contain actions that are important, but aren't the primary action in an app.TextButton
: Clickable text, without a border. Since text buttons don't have visible borders, they must rely on their position relative to other content for context.IconButton
: A button with an icon.FloatingActionButton
: An icon button that hovers over content to promote a primary action.
Video:
There are usually 3 main aspects to constructing a button: style, callback, and its child, as seen in the following ElevatedButton
sample code:
A button's callback function,
onPressed
, determines what happens when the button is clicked, therefore, this function is where you update your app state. If the callback isnull
, the button is disabled and nothing happens when a user presses the button.The button's
child
, which is displayed within the button's content area, is usually text or an icon that indicates the button's purpose.Finally, a button's
style
controls its appearance: color, border, and so on.
Checkpoint: Complete this tutorial that teaches you how to build a "favorite" button:
ElevatedButton
• FilledButton
• OutlinedButton
• TextButton
• IconButton
• FloatingActionButton
Text
#Several widgets support text input.
SelectableText
#Flutter's Text
widget displays text on the screen, but doesn't allow users to highlight or copy the text. SelectableText
displays a string of user-selectable text.
Video:
RichText
#RichText
lets you display strings of rich text in your app. TextSpan
, similar to RichText
, allows you to display parts of text with different text styles. It's not for handling user input, but is useful if you're allowing users edit and format text.
Video:
Demo:
Code:
TextField
#A TextField
lets users enter text in text box using a hardware or onscreen keyboard.
TextField
s have many different properties and configurations. A few of the highlights:
InputDecoration
determines the text field's appearance, such as color and border.controller
: ATextEditingController
controls the text being edited. Why might you need a controller? By default, your app's users can type into the text field, but if you want to programmatically control theTextField
and clear its value, for example, you'll need aTextEditingController
.onChanged
: This callback function triggers when the user changes the text field's value, such as when inserting or removing text.onSubmitted
: This callback is triggered when the user indicates that they are done editing the text in the field; for example, by tapping the "enter" key when the text field is in focus.
The class supports other configurable properties, such as obscureText
that turns each letter into a readOnly
circle as its entered and readOnly
which prevents the user from changing the text.
Checkpoint: Complete this 4-part cookbook series that walks you through how to create a text field, retrieve its value, and update your app state:
Form
#Form
is an optional container for grouping together multiple form field widgets, such as TextField
.
Each individual form field should be wrapped in a FormField
widget with the Form
widget as a common ancestor. Convenience widgets exist that pre-wrap form field widgets in a FormField
for you. For example, the Form
widget version of TextField
is TextFormField
.
Using a Form
provides access to a FormState
, which lets you save, reset, and validate each FormField
that descends from this Form
. You can also provide a GlobalKey
to identify a specific form, as shown in the following code:
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
TextFormField(
decoration: const InputDecoration(
hintText: 'Enter your email',
),
validator: (String? value) {
if (value == null || value.isEmpty) {
return 'Please enter some text';
}
return null;
},
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: ElevatedButton(
onPressed: () {
// Validate returns true if the form is valid, or false otherwise.
if (_formKey.currentState!.validate()) {
// Process data.
}
},
child: const Text('Submit'),
),
),
],
),
);
}
Checkpoint: Complete this tutorial to learn how to
Demo:
Code:
TextField
• RichText
• SelectableText
• Form
Select a value from a group of options
#Provide a way to users to select from several options.
SegmentedButton
#SegmentedButton
allows users to select from a minimal group of 2-5 items.
The data type, <T>
, can be a built-in type such as int
, String
, bool
or an enum. A SegmentedButton
has a few relevant properties:
segments
, a list ofButtonSegment
s, where each represents a "segment" or option that the user can select. Visually, eachButtonSegment
can have an icon, text label, or both.multiSelectionEnabled
indicates whether the user is allowed to select multiple options. This property defaults to false.selected
identifies the currently selected value(s). Note:selected
is of type ofSet<T>
, so if you're only allowing users to select one value, that value must be provided as aSet
with a single element.The
onSelectionChanged
callback triggers when a user selects any segments. It provides a list of the selected segments so you can update your app state.Additional styling parameters allow you to modify the button's appearance. For example,
style
takes aButtonStyle
, providing a way to configure aselectedIcon
.
Chip
#Chip
is a compact way of representing an attribute, text, entity, or action for a specific context. Specialized Chip
widgets exist for specific use cases:
- InputChip represents a complex piece of information, such as an entity (person, place, or thing), or conversational text, in a compact form.
- ChoiceChip allows a single selection from a set of options. Choice chips contain related descriptive text or categories.
- FilterChip uses tags or descriptive words to filter content.
- ActionChip represents an action related to primary content.
Every Chip
widget requires a label
. It can optionally have an avatar
(such as an icon or a user's profile picture) and an onDeleted
callback, which shows a delete icon that when triggered, deletes the chip. A Chip
widget's appearance can also be customized by setting a number of optional parameters such as shape
, color
, and iconTheme
.
You will typically use Wrap
, a widget that displays its children in multiple horizontal or vertical runs, to make sure your chips wrap and don't get cut off at the edge of your app.
DropdownMenu
#A DropdownMenu
allows users to select a choice from a menu of options and places the selected text into a TextField
. It also allows users to filter the menu items based on the text input.
Configuration parameters include the following:
dropdownMenuEntries
provides a list ofDropdownMenuEntry
s that describes each menu item. The menu might contain information such as a text label, and a leading or trailing icon. (This is also the only required parameter.)TextEditingController
allows programmatically controlling theTextField
.- The
onSelected
callback triggers when the user selects an option. initialSelection
allows you to configure the default value.- Additional parameters are also available for customizing the widget's look and behavior.
Video:
Slider
#The Slider
widget lets a user adjust a value by moving an indicator, such as a volume bar.
Configuration parameters for the Slider
widget:
value
represents the slider's current valueonChanged
is the callback that gets triggered when the handle is movedmin
andmax
establish minimum and maximum values allowed by the sliderdivisions
establishes a discrete interval with which the user can move the handle along the track.
Video:
SegmentedButton
• DropdownMenu
• Slider
• Chip
Toggle between values
#There are several ways that your UI can allow toggling between values.
Checkbox, Switch, and Radio
#Provide an option to toggle a single value on and off. The functional logic behind these widgets are the same, as all 3 are built on top of ToggleableStateMixin
, though each provides slight presentation differences.:
Checkbox
is a container that is empty when false or filled with a checkmark when true.Switch
has a handle that is on the left when false and slides to the right when true.Radio
is similar to aCheckbox
in that it's a container that is empty when false, but filled in when true.
The configuration for Checkbox
and Switch
contain:
- a
value
that istrue
orfalse
- and an
onChanged
callback which is triggered when the user toggles the widget
Checkbox
#Switch
#Radio
#A group of Radio
buttons that allows the user to select between mutually exclusive values. When the user selects a radio button in a group, the other radio buttons are unselected.
- A particular
Radio
button'svalue
represent that button's value, - The selected value for a group of radio buttons is identified by the
groupValue
parameter. Radio
also has anonChanged
callback that gets triggered when users click it, likeSwitch
andCheckbox
Bonus: CheckboxListTile & SwitchListTile
#These convenience widgets are the same checkbox and switch widgets, but support a label (as a ListTile
).
Video:
Video:
Checkbox
• CheckboxListTile
• Switch
• SwitchListTile
• Radio
Select a date or time
#Widgets are provided so the user can select a date and time.
There is a set of dialogs that enable users to select a date or time, as you'll see in the following sections. With the exception of differing date types - DateTime
for dates vs TimeOfDay
for time - these dialogs function similarly, you can configure them by providing:
- a default
initialDate
orinitialTime
- or an
initialEntryMode
that determines the picker UI that's displayed.
DatePickerDialog
#This dialog allows the user to select a date or a range of dates. Activate by calling the showDatePicker
function, which returns a Future<DateTime>
, so don't forget to await the asynchronous function call!
TimePickerDialog
#TimePickerDialog
is a dialog that presents a time picker. It can be activated by calling the showTimePicker()
function. Instead of returning a Future<DateTime>
, showTimePicker
instead returns a Future<TimeOfDay>
. Once again, don't forget to await the function call!
showDatePicker
• showTimePicker
Swipe & slide
#A Dismissible
is a widget that enables users to dismiss it by swiping. It has a number of configuration parameters, including:
- A
child
widget - An
onDismissed
callback that is triggered when the user swipes - Styling parameters such as
background
- It's important to include a
key
object as well so that they can be uniquely identified from siblingDismissible
widgets in the widget tree.
Video:
implement swipe to dismiss using the dismissible widget.
Checkpoint: Complete this tutorial on how to
API Docs:
Looking for more widgets?
#This page features just a few of the common Material widgets that you can use for handling user input in your Flutter app. Check out the Material Widget library and Material Library API docs for a full list of widgets.
Material 3 Demo for a curated sample of user input widgets available in the Material library.
Demo: See Flutter's
If the Material and Cupertino libraries don't have a widget that does what you need, check out pub.dev to find Flutter & Dart community-owned and maintained packages. For example, the flutter_slidable
package provides a Slidable
widget that is more customizable than the Dismissible
widget described in the previous section.
Video:
Build interactive widgets with GestureDetector
#Have you scoured the widget libraries, pub.dev, asked your coding friends, and still can't find a widget that fits the user interaction that you're looking for? You can build your own custom widget and make it interactive using GestureDetector
.
Checkpoint: Use this recipe as a starting point to create your own custom button widget that can
Video:
Taps, drags, and other gestures which explains how to listen for, and respond to, gestures in Flutter.
Reference: Check out
Bonus Video: Curious how Flutter's
GestureArena
turns raw user interaction data into human recognizable concepts like taps, drags, and pinches? Check out this video: GestureArena (Decoding Flutter)
Don't forget about accessibility!
#If you're building a custom widget, annotate its meaning with the Semantics
widget. It provides descriptions and metadata to screen readers and other semantic analysis-based tools.
Video:
API Docs:
Testing
#Once you have finished building user interactions into your app, don't forget to write tests to ensure that everything works as expected!
These tutorials walk you through writing tests that simulate user interactions in your app:
tap, drag, and enter text cookbook article and learn how to use
Checkpoint: Follow thisWidgetTester
to simulate and test user interactions in your app.
handle scrolling cookbook recipe shows you how to verify that lists of widgets contain the expected content by scrolling through the lists using widget tests.
Bonus Tutorial: The
Next: Networking
#This page was an introduction to handling user input. Now that you know how to handle input from app users, you can make your app even more interesting by adding external data. In the next section, you'll learn now to fetch data for your app over a network, how to convert data to and from JSON, authentication, and other networking features.
Feedback
#As this section of the website is evolving, we welcome your feedback!
Unless stated otherwise, the documentation on this site reflects the latest stable version of Flutter. Page last updated on 2024-09-26. View source or report an issue.