Movatterモバイル変換


[0]ホーム

URL:


Skip to main content

docs.flutter.dev uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic.

Learn more

Flutter 3.38 and Dart 3.10 are here!Learn more

Handling user input

Learn how to handle user input in Flutter.

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, likescrolling, have already been covered inLayouts.

About design system support

Flutter ships with prebuilt components for two design systems as part of the SDK,Material andCupertino. For educational purposes, this page focuses on Material widgets, components that are stylized according to theMaterial 3 design language specifications.

The Flutter community onpub.dev, the package repository for Dart and Flutter, create and support additional design languages such asFluent UI,macOS UI, and more. If the existing design system components don't quite fit what you need, Flutter lets you build your own custom widgets, which is covered at the end of this section. No matter which design system you choose, the principals on this page apply.

Reference: Thewidget catalog has an inventory of commonly used widgets in theMaterial andCupertino libraries.

Next, we'll cover a few of the Material widgets that support common use cases for handling user input in your Flutter app.

Buttons

#

A collection of Material 3 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, likeSave,Join now, orConfirm.
  • Tonal Button: A middle ground button betweenFilledButton andOutlinedButton. They're useful in contexts where a lower-priority button requires more emphasis than an outline, likeNext.
  • 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:FloatingActionButton (Widget of the Week)

There are usually 3 main aspects to constructing a button: style, callback, and its child, as seen in the followingElevatedButton 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'schild, which is displayed within the button's content area, is usually text or an icon that indicates the button's purpose.

  • Finally, a button'sstyle controls its appearance: color, border, and so on.

A GIF of an elevated button with the text 'Enabled'

This figure shows an ElevatedButton with the text 'Enabled' being clicked.

dart
intcount=0;@overrideWidgetbuild(BuildContextcontext){returnElevatedButton(style:ElevatedButton.styleFrom(textStyle:constTextStyle(fontSize:20),),onPressed:(){setState((){count+=1;});},child:constText('Enabled'),);}

Checkpoint: Complete this tutorial that teaches you how to build a "favorite" button:Add interactivity to your Flutter app


API Docs:ElevatedButtonFilledButtonOutlinedButtonTextButtonIconButtonFloatingActionButton

Text

#

Several widgets support text input.

SelectableText

#

Flutter'sText widget displays text on the screen, but doesn't allow users to highlight or copy the text.SelectableText displays a string ofuser-selectable text.

A GIF of a cursor highlighting two lines of text from a paragraph.

This figure shows a cursor highlighting a portion of a string of text.

dart
@overrideWidgetbuild(BuildContextcontext){returnconstSelectableText('''Two households, both alike in dignity,In fair Verona, where we lay our scene,From ancient grudge break to new mutiny,Where civil blood makes civil hands unclean.From forth the fatal loins of these two foes''');}

Video:SelectableText (Widget of the Week)

RichText

#

RichText lets you display strings of rich text in your app.TextSpan, similar toRichText, 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.

A screenshot of the text "Hello bold world!" with the word "bold" in bold font.

This figure shows a string of text formatted with different text styles.

dart
@overrideWidgetbuild(BuildContextcontext){returnRichText(text:TextSpan(text:'Hello',style:DefaultTextStyle.of(context).style,children:const<TextSpan>[TextSpan(text:'bold',style:TextStyle(fontWeight:FontWeight.bold)),TextSpan(text:' world!'),],),);}

Video:Rich Text (Widget of the Week)

Code:Rich Text Editor code

TextField

#

ATextField lets users enter text in text box using a hardware or onscreen keyboard.

TextFields 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 asobscureText that turns each letter into areadOnly circle as its entered andreadOnly which prevents the user from changing the text.

A GIF of a text field with the label 'Mascot Name', purple focus border and the phrase 'Dash the hummingbird' being typed in.

This figure shows text being typed into a TextField with a selected border and label.

dart
finalTextEditingController_controller=TextEditingController();@overrideWidgetbuild(BuildContextcontext){returnTextField(controller:_controller,decoration:constInputDecoration(border:OutlineInputBorder(),labelText:'Mascot Name',),);}

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:

  1. Create and style a text field
  2. Retrieve the value of a text field
  3. Handle changes to a text field
  4. Focus and text fields.

Form

#

Form is an optional container for grouping together multiple form field widgets, such asTextField.

Each individual form field should be wrapped in aFormField widget with theForm widget as a common ancestor. Convenience widgets exist that pre-wrap form field widgets in aFormField for you. For example, theForm widget version ofTextField isTextFormField.

Using aForm provides access to aFormState, which lets you save, reset, and validate eachFormField that descends from thisForm. You can also provide aGlobalKey to identify a specific form, as shown in the following code:

dart
finalGlobalKey<FormState>_formKey=GlobalKey<FormState>();@overrideWidgetbuild(BuildContextcontext){returnForm(key:_formKey,child:Column(crossAxisAlignment:CrossAxisAlignment.start,children:<Widget>[TextFormField(decoration:constInputDecoration(hintText:'Enter your email',),validator:(String?value){if(value==null||value.isEmpty){return'Please enter some text';}returnnull;},),Padding(padding:constEdgeInsets.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:constText('Submit'),),),],),);}

Checkpoint: Complete this tutorial to learn how tobuild a form with validation.

Demo:Form app

Code:Form app code


API Docs:TextFieldRichTextSelectableTextForm

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 asint,String,bool or an enum. ASegmentedButton has a few relevant properties:

  • segments, a list ofButtonSegments, 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.

  • TheonSelectionChanged 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.

A GIF of a SegmentedButton with 4 segments: Day, Week, Month, and Year. Each has a calendar icon to represent its value and a text label. Day is first selected, then week and month, then year.

This figure shows a SegmentedButton, each segment with an icon and text representing its value.

dart
enumCalendar{day,week,month,year}// StatefulWidget...CalendarcalendarView=Calendar.day;@overrideWidgetbuild(BuildContextcontext){returnSegmentedButton<Calendar>(segments:const<ButtonSegment<Calendar>>[ButtonSegment<Calendar>(value:Calendar.day,label:Text('Day'),icon:Icon(Icons.calendar_view_day)),ButtonSegment<Calendar>(value:Calendar.week,label:Text('Week'),icon:Icon(Icons.calendar_view_week)),ButtonSegment<Calendar>(value:Calendar.month,label:Text('Month'),icon:Icon(Icons.calendar_view_month)),ButtonSegment<Calendar>(value:Calendar.year,label:Text('Year'),icon:Icon(Icons.calendar_today)),],selected:<Calendar>{calendarView},onSelectionChanged:(Set<Calendar>newSelection){setState((){// By default, there is only a single segment that can be// selected at a time, so its value is always the firstcalendarView=newSelection.first;});},);}

Chip

#

Chip is a compact way of representing an attribute, text, entity, or action for a specific context. SpecializedChip 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.

EveryChip widget requires alabel. It can optionally have anavatar (such as an icon or a user's profile picture) and anonDeleted callback, which shows a delete icon that when triggered, deletes the chip. AChip widget's appearance can also be customized by setting a number of optional parameters such asshape,color, andiconTheme.

You will typically useWrap, 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.

A screenshot of 4 Chips split over two rows with a leading circular profile image with content text.

This figure shows two rows of Chip widgets, each containing a circular leading profile image and content text.

dart
@overrideWidgetbuild(BuildContextcontext){returnconstSizedBox(width:500,child:Wrap(alignment:WrapAlignment.center,spacing:8,runSpacing:4,children:[Chip(avatar:CircleAvatar(backgroundImage:AssetImage('assets/images/dash_chef.png')),label:Text('Chef Dash'),),Chip(avatar:CircleAvatar(backgroundImage:AssetImage('assets/images/dash_firefighter.png')),label:Text('Firefighter Dash'),),Chip(avatar:CircleAvatar(backgroundImage:AssetImage('assets/images/dash_musician.png')),label:Text('Musician Dash'),),Chip(avatar:CircleAvatar(backgroundImage:AssetImage('assets/images/dash_artist.png')),label:Text('Artist Dash'),),],),);}

DropdownMenu

#

ADropdownMenu allows users to select a choice from a menu of options and places the selected text into aTextField. It also allows users to filter the menu items based on the text input.

Configuration parameters include the following:

  • dropdownMenuEntries provides a list ofDropdownMenuEntrys 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.
  • TheonSelected 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.
A GIF the DropdownMenu widget that is selected, it displays 5 options: Blue, Pink, Green, Orange, and Grey. The option text is displayed in the color of its value.

This figure shows a DropdownMenu widget with 5 value options. Each option's text color is styled to represent the color value.

dart
enumColorLabel{blue('Blue',Colors.blue),pink('Pink',Colors.pink),green('Green',Colors.green),orange('Orange',Colors.orange),grey('Grey',Colors.grey);constColorLabel(this.label,this.color);finalStringlabel;finalColorcolor;}// StatefulWidget...@overrideWidgetbuild(BuildContextcontext){returnDropdownMenu<ColorLabel>(initialSelection:ColorLabel.green,controller:colorController,// requestFocusOnTap is enabled/disabled by platforms when it is null.// On mobile platforms, this is false by default. Setting this to true will// trigger focus request on the text field and virtual keyboard will appear// afterward. On desktop platforms however, this defaults to true.requestFocusOnTap:true,label:constText('Color'),onSelected:(ColorLabel?color){setState((){selectedColor=color;});},dropdownMenuEntries:ColorLabel.values.map<DropdownMenuEntry<ColorLabel>>((ColorLabelcolor){returnDropdownMenuEntry<ColorLabel>(value:color,label:color.label,enabled:color.label!='Grey',style:MenuItemButton.styleFrom(foregroundColor:color.color,),);}).toList(),);}

Video:DropdownMenu (Widget of the Week)

Slider

#

TheSlider widget lets a user adjust a value by moving an indicator, such as a volume bar.

Configuration parameters for theSlider widget:

  • value represents the slider's current value
  • onChanged is the callback that gets triggered when the handle is moved
  • min andmax establish minimum and maximum values allowed by the slider
  • divisions establishes a discrete interval with which the user can move the handle along the track.
A GIF of a slider that has the dial dragged left to right in increments of 1, from 0.0 to 5.0

This figure shows a slider widget with a value ranging from 0.0 to 5.0 broken up into 5 divisions. It shows the current value as a label as the dial is dragged.

dart
double_currentVolume=1;@overrideWidgetbuild(BuildContextcontext){returnSlider(value:_currentVolume,max:5,divisions:5,label:_currentVolume.toString(),onChanged:(doublevalue){setState((){_currentVolume=value;});},);}

Video:Slider, RangeSlider, CupertinoSlider (Widget of the Week)


API Docs:SegmentedButtonDropdownMenuSliderChip

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 ofToggleableStateMixin, 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 forCheckbox andSwitch contain:

  • avalue that istrue orfalse
  • and anonChanged callback which is triggered when the user toggles the widget

Checkbox

#
A GIF that shows a pointer clicking a checkbox and then clicking again to uncheck it.

This figure shows a checkbox being checked and unchecked.

dart
boolisChecked=false;@overrideWidgetbuild(BuildContextcontext){returnCheckbox(checkColor:Colors.white,value:isChecked,onChanged:(bool?value){setState((){isChecked=value!;});},);}

Switch

#
A GIF of a Switch widget that is toggled on and off. In its off state, it is gray with dark gray borders. In its on state, it is red with a light red border.

This figure shows a Switch widget that is toggled on and off.

dart
boollight=true;@overrideWidgetbuild(BuildContextcontext){returnSwitch(// This bool value toggles the switch.value:light,activeThumbColor:Colors.red,onChanged:(boolvalue){// This is called when the user toggles the switch.setState((){light=value;});},);}

Radio

#

ARadioGroup containsRadio buttons that allow 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 particularRadio button'svalue represent that button's value.
  • The selected value for aRadioGroup is identified by thegroupValue parameter.
  • RadioGroup has anonChanged callback that gets triggered when users click it, likeSwitch andCheckbox.
A GIF of 4 ListTiles in a column, each containing a leading Radio button and title text. The Radio buttons are selected in order from top to bottom.

This figure shows a column of ListTiles containing a radio button and label, where only one radio button can be selected at a time.

dart
enumCharacter{musician,chef,firefighter,artist}classRadioExampleextendsStatefulWidget{constRadioExample({super.key});@overrideState<RadioExample>createState()=>_RadioExampleState();}class_RadioExampleStateextendsState<RadioExample>{Character?_character=Character.musician;voidsetCharacter(Character?value){setState((){_character=value;});}@overrideWidgetbuild(BuildContextcontext){returnRadioGroup(groupValue:_character,onChanged:setCharacter,child:Column(children:<Widget>[ListTile(title:constText('Musician'),leading:Radio<Character>(value:Character.musician),),ListTile(title:constText('Chef'),leading:Radio<Character>(value:Character.chef),),ListTile(title:constText('Firefighter'),leading:Radio<Character>(value:Character.firefighter),),ListTile(title:constText('Artist'),leading:Radio<Character>(value:Character.artist),),],),);}}

Bonus: CheckboxListTile & SwitchListTile

#

These convenience widgets are the same checkbox and switch widgets, but support a label (as aListTile).

A GIF of a column containing a CheckboxListTile and a SwitchListTile being toggled.

This figure shows a column containing a CheckboxListTile and a SwitchListTile being toggled.

dart
doubletimeDilation=1.0;bool_lights=false;@overrideWidgetbuild(BuildContextcontext){returnColumn(children:[CheckboxListTile(title:constText('Animate Slowly'),value:timeDilation!=1.0,onChanged:(bool?value){setState((){timeDilation=value!?10.0:1.0;});},secondary:constIcon(Icons.hourglass_empty),),SwitchListTile(title:constText('Lights'),value:_lights,onChanged:(boolvalue){setState((){_lights=value;});},secondary:constIcon(Icons.lightbulb_outline),),],);}

Video:CheckboxListTile (Widget of the Week)

Video:SwitchListTile (Widget of the Week)


API Docs:CheckboxCheckboxListTileSwitchSwitchListTileRadio

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 vsTimeOfDay for time - these dialogs function similarly, you can configure them by providing:

  • a defaultinitialDate orinitialTime
  • or aninitialEntryMode 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 theshowDatePicker function, which returns aFuture<DateTime>, so don't forget to await the asynchronous function call!

A GIF of a pointer clicking a button that says 'Pick a date', then shows a date picker. The date Friday, August 30 is selected and the 'OK' button is clicked.

This figure shows a DatePicker that is displayed when the 'Pick a date' button is clicked.

dart
DateTime?selectedDate;@overrideWidgetbuild(BuildContextcontext){vardate=selectedDate;returnColumn(children:[Text(date==null?'You haven\\\'t picked a date yet.':DateFormat('MM-dd-yyyy').format(date),),ElevatedButton.icon(icon:constIcon(Icons.calendar_today),onPressed:()async{varpickedDate=awaitshowDatePicker(context:context,initialEntryMode:DatePickerEntryMode.calendarOnly,initialDate:DateTime.now(),firstDate:DateTime(2019),lastDate:DateTime(2050),);setState((){selectedDate=pickedDate;});},label:constText('Pick a date'),)]);}

TimePickerDialog

#

TimePickerDialog is a dialog that presents a time picker. It can be activated by calling theshowTimePicker() function. Instead of returning aFuture<DateTime>,showTimePicker instead returns aFuture<TimeOfDay>. Once again, don't forget to await the function call!

A GIF of a pointer clicking a button that says 'Pick a time', then shows a time picker. The time picker shows a circular clock as the cursor moves the hour hand, then minute hand, selects PM, then the 'OK' button is clicked.

This figure shows a TimePicker that is displayed when the 'Pick a time' button is clicked.

dart
TimeOfDay?selectedTime;@overrideWidgetbuild(BuildContextcontext){vartime=selectedTime;returnColumn(children:[Text(time==null?'You haven\\\'t picked a time yet.':time.format(context),),ElevatedButton.icon(icon:constIcon(Icons.calendar_today),onPressed:()async{varpickedTime=awaitshowTimePicker(context:context,initialEntryMode:TimePickerEntryMode.dial,initialTime:TimeOfDay.now(),);setState((){selectedTime=pickedTime;});},label:constText('Pick a time'),)]);}
Tip

CallingshowDatePicker() andshowTimePicker() is equivalent to callingshowDialog() withDatePickerDialog() andTimePickerDialog(), respectively. Internally, both functions use theshowDialog() function with their respectiveDialog widgets. To enable state restoration, you can also pushDatePickerDialog() andTimePickerDialog() directly on to theNavigator stack.


API Docs:showDatePickershowTimePicker

Swipe & slide

#

ADismissible is a widget that enables users to dismiss it by swiping. It has a number of configuration parameters, including:

  • Achild widget
  • AnonDismissed callback that is triggered when the user swipes
  • Styling parameters such asbackground
  • It's important to include akey object as well so that they can be uniquely identified from siblingDismissible widgets in the widget tree.
A GIF of a list of Dismissible widgets that each contain a ListTile. Swiping across the ListTile reveals a green background and makes the tile disappear.

This figure shows a list of Dismissible widgets that each contain a ListTile. Swiping across the ListTile reveals a green background and makes the tile disappear.

dart
List<int>items=List<int>.generate(100,(intindex)=>index);@overrideWidgetbuild(BuildContextcontext){returnListView.builder(itemCount:items.length,padding:constEdgeInsets.symmetric(vertical:16),itemBuilder:(BuildContextcontext,intindex){returnDismissible(background:Container(color:Colors.green,),key:ValueKey<int>(items[index]),onDismissed:(DismissDirectiondirection){setState((){items.removeAt(index);});},child:ListTile(title:Text('Item${items[index]}',),),);},);}

Video:Dismissible (Widget of the Week)

Checkpoint: Complete this tutorial on how toimplement swipe to dismiss using the dismissible widget.


API Docs:Dismissible

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 theMaterial Widget library andMaterial Library API docs for a full list of widgets.

Demo: See Flutter'sMaterial 3 Demo for a curated sample of user input widgets available in the Material library.

If the Material and Cupertino libraries don't have a widget that does what you need, check outpub.dev to find Flutter & Dart community-owned and maintained packages. For example, theflutter_slidable package provides aSlidable widget that is more customizable than theDismissible widget described in the previous section.

Video:flutter_slidable (Package of the Week)

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 usingGestureDetector.

Checkpoint: Use this recipe as a starting point to create your owncustom button widget that canhandle taps.

Video:GestureDetector (Widget of the Week)

Reference: Check outTaps, drags, and other gestures which explains how to listen for, and respond to, gestures in Flutter.

Bonus Video: Curious how Flutter'sGestureArena 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 theSemantics widget. It provides descriptions and metadata to screen readers and other semantic analysis-based tools.

Video:Semantics (Flutter Widget of the Week)


API Docs:GestureDetectorSemantics

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:

Checkpoint: Follow thistap, drag, and enter text cookbook article and learn how to useWidgetTester to simulate and test user interactions in your app.

Bonus Tutorial: Thehandle scrolling cookbook recipe shows you how to verify that lists of widgets contain the expected content by scrolling through the lists using widget tests.

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 how 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, wewelcome your feedback!

Was this page's content helpful?

Unless stated otherwise, the documentation on this site reflects Flutter 3.38.1. Page last updated on 2025-12-8.View source orreport an issue.


[8]ページ先頭

©2009-2025 Movatter.jp