CINXE.COM
Interactivity | Flutter
<!doctype html><html lang="en"><head><meta charset="utf-8"><title>Interactivity | Flutter</title><link rel="icon" href="/assets/images/branding/flutter/icon/64.png" eleventy:ignore><link rel="apple-touch-icon" href="/assets/images/branding/flutter/logo/flutter-logomark-320px.png" eleventy:ignore><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="theme-color" content="#ffffff"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><meta name="google-site-verification" content="HFqxhSbf9YA_0rBglNLzDiWnrHiK_w4cqDh2YD2GEY4"><script>!function(e,t,a,n){e[n]=e[n]||[],e[n].push({"gtm.start":(new Date).getTime(),event:"gtm.js"});var g=t.getElementsByTagName(a)[0],m=t.createElement(a);m.async=!0,m.src="https://www.googletagmanager.com/gtm.js?id=GTM-ND4LWWZ",g.parentNode.insertBefore(m,g)}(window,document,"script","dataLayer")</script><script>!function(e,a,t,n,c,o,s){e.GoogleAnalyticsObject=c,e[c]=e[c]||function(){(e[c].q=e[c].q||[]).push(arguments)},e[c].l=1*new Date,o=a.createElement(t),s=a.getElementsByTagName(t)[0],o.async=1,o.src="//www.google-analytics.com/analytics.js",s.parentNode.insertBefore(o,s)}(window,document,"script",0,"ga"),ga("create","UA-67589403-1","auto"),ga("send","pageview")</script><meta name="description" content="How to implement a stateful widget that responds to taps."><meta name="twitter:card" content="summary_large_image"><meta name="twitter:site" content="@flutterdev"><meta property="og:title" content="Add interactivity to your Flutter app"><meta property="og:url" content="https://docs.flutter.dev/ui/interactivity"><meta property="og:description" content="How to implement a stateful widget that responds to taps."><meta property="og:image" content="https://docs.flutter.dev/assets/images/flutter-logo-sharing.png" eleventy:ignore><link href="https://fonts.googleapis.com/css2?family=Google+Sans:wght@400;500;700&display=swap" rel="stylesheet"><link href="https://fonts.googleapis.com/css2?family=Google+Sans+Text:wght@400;500;700&display=swap" rel="stylesheet"><link href="https://fonts.googleapis.com/css2?family=Google+Sans+Mono:wght@400;500;700&display=swap" rel="stylesheet"><link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0" rel="stylesheet"><script>window.__CALLBACKS=[]</script><link rel="stylesheet" href="/assets/css/main.css"></head><body><a href="#site-content-title" id="skip">Skip to main content</a><section id="cookie-notice"><div class="container"><p>docs.flutter.dev uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. <a href="https://policies.google.com/technologies/cookies" target="_blank" rel="noopener">Learn more</a>.</p><button id="cookie-consent" class="btn btn-primary">OK, got it</button></div></section><noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-ND4LWWZ" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript><div id="overlay-under-drawer"></div><header class="site-header"><nav class="navbar navbar-expand-md justify-content-start justify-content-md-between"><button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"><i class="material-symbols">menu</i></button> <a class="navbar-brand" href="/"><img src="/assets/images/branding/flutter/logo+text/horizontal/default.svg" alt="Flutter logo" height="37" width="129" class="align-middle"></a><div id="navbarSupportedContent" class="collapse navbar-collapse flex-grow-0"><div class="site-header__sheet-bg" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"></div><div class="site-header__sheet"><ul class="navbar-nav"><div class="site-sidebar site-sidebar--header d-md-none"><ul class="nav flex-column"><li class="nav-header">Get started</li><li class="nav-item"><a class="nav-link" href="/get-started/install">Set up Flutter</a></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#header-sidenav-3" role="button" aria-expanded="false" aria-controls="header-sidenav-3">Learn Flutter</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-3"><li class="nav-item"><a class="nav-link" href="/get-started/learn-flutter">Introduction</a></li><li class="nav-item"><a class="nav-link" href="/get-started/codelab">Write your first app</a></li><li class="nav-item"><a class="nav-link collapsible" data-toggle="collapse" data-target="#header-sidenav-3-3" href="#header-sidenav-3-3" role="button" aria-expanded="true" aria-controls="header-sidenav-3-3">Learn the fundamentals</a><ul class="nav flex-column flex-nowrap collapse show" id="header-sidenav-3-3"><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals">Introduction</a></li><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals/dart">Intro to Dart</a></li><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals/widgets">Widgets</a></li><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals/layout">Layout</a></li><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals/state-management">State management</a></li><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals/user-input">Handling user input</a></li><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals/networking">Networking and data</a></li><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals/local-caching">Local data and caching</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-3-4" href="/get-started/flutter-for" role="button" aria-expanded="false" aria-controls="header-sidenav-3-4">From another platform?</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-3-4"><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/android-devs">Flutter for Android devs</a></li><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/swiftui-devs">Flutter for SwiftUI devs</a></li><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/uikit-devs">Flutter for UIKit devs</a></li><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/react-native-devs">Flutter for React Native devs</a></li><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/web-devs">Flutter for web devs</a></li><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/xamarin-forms-devs">Flutter for Xamarin.Forms devs</a></li><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/declarative">Introduction to declarative UI</a></li><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/dart-swift-concurrency">Flutter versus Swift concurrency</a></li></ul></li><div class="dropdown-divider"></div><li class="nav-item"><a class="nav-link" href="/codelabs">Codelabs</a></li><li class="nav-item"><a class="nav-link" href="/cookbook">Cookbook</a></li><li class="nav-item"><a class="nav-link" href="https://flutter.github.io/samples/" target="_blank" rel="noopener">Demos and samples</a></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#header-sidenav-4" role="button" aria-expanded="false" aria-controls="header-sidenav-4">Stay up to date</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-4"><li class="nav-item"><a class="nav-link" href="/release/upgrade">Upgrade</a></li><li class="nav-item"><a class="nav-link" href="/release/archive">SDK archive</a></li><div class="dropdown-divider"></div><li class="nav-item"><a class="nav-link" href="/release/whats-new">What's new</a></li><li class="nav-item"><a class="nav-link" href="/release/release-notes">Release notes</a></li><li class="nav-item"><a class="nav-link" href="/release/breaking-changes">Breaking changes</a></li><li class="nav-item"><a class="nav-link" href="/release/compatibility-policy">Compatibility policy</a></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#header-sidenav-5" role="button" aria-expanded="false" aria-controls="header-sidenav-5">App solutions</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-5"><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-5-1" href="#header-sidenav-5-1" role="button" aria-expanded="false" aria-controls="header-sidenav-5-1">AI</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-5-1"><li class="nav-item"><a class="nav-link" href="/resources/ai-overview">Overview</a></li><li class="nav-item"><a class="nav-link" href="https://ai.google.dev/gemini-api/docs/get-started/dart" target="_blank" rel="noopener">Get started with the Gemini API</a></li><li class="nav-item"><a class="nav-link" href="https://pub.dev/packages/google_generative_ai" target="_blank" rel="noopener">Google AI Dart SDK (pub.dev)</a></li><li class="nav-item"><a class="nav-link" href="https://www.youtube.com/watch?v=1AuzJEiHjO4" target="_blank" rel="noopener">Build with Google AI Dart SDK (video)</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-5-2" href="#header-sidenav-5-2" role="button" aria-expanded="false" aria-controls="header-sidenav-5-2">Firebase & Firestore</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-5-2"><li class="nav-item"><a class="nav-link" href="/data-and-backend/firebase">Overview</a></li><li class="nav-item"><a class="nav-link" href="https://firebase.google.com/docs/flutter" target="_blank" rel="noopener">Discover Firebase for Flutter</a></li><li class="nav-item"><a class="nav-link" href="https://www.youtube.com/watch?v=wUSkeTaBonA" target="_blank" rel="noopener">Get to know Firebase for Flutter</a></li><li class="nav-item"><a class="nav-link" href="https://firebase.google.com/codelabs/firebase-auth-in-flutter-apps" target="_blank" rel="noopener">Add a user authentication flow to a Flutter app using FirebaseUI</a></li><li class="nav-item"><a class="nav-link" href="https://firebase.google.com/codelabs/firebase-get-to-know-web" target="_blank" rel="noopener">Get to know Firebase for web</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-5-3" href="#header-sidenav-5-3" role="button" aria-expanded="false" aria-controls="header-sidenav-5-3">Games</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-5-3"><li class="nav-item"><a class="nav-link" href="/resources/games-toolkit">Overview</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/games/achievements-leaderboard">Add achievements and leaderboards</a></li><li class="nav-item"><a class="nav-link" href="https://firebase.google.com/codelabs/build-leaderboards-with-firestore#0" target="_blank" rel="noopener">Build leaderboards with Firestore</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/plugins/google-mobile-ads">Add advertising</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/games/firestore-multiplayer">Add multiplayer support</a></li><li class="nav-item"><a class="nav-link" href="https://codelabs.developers.google.com/codelabs/flutter-in-app-purchases" target="_blank" rel="noopener">Add in-app purchases</a></li><li class="nav-item"><a class="nav-link" href="https://firebase.google.com/codelabs/firebase-auth-in-flutter-apps" target="_blank" rel="noopener">Add user authentication</a></li><li class="nav-item"><a class="nav-link" href="https://firebase.google.com/docs/crashlytics/get-started?platform=flutter" target="_blank" rel="noopener">Debug using Crashlytics</a></li><li class="nav-item"><a class="nav-link" href="https://codelabs.developers.google.com/codelabs/flutter-flame-brick-breaker" target="_blank" rel="noopener">Intro to Flame with Flutter</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-5-4" href="#header-sidenav-5-4" role="button" aria-expanded="false" aria-controls="header-sidenav-5-4">Monetization</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-5-4"><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-5-4-1" href="#header-sidenav-5-4-1" role="button" aria-expanded="false" aria-controls="header-sidenav-5-4-1">Advertising</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-5-4-1"><li class="nav-item"><a class="nav-link" href="/resources/ads-overview">Ads overview</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/plugins/google-mobile-ads">Add advertising</a></li><li class="nav-item"><a class="nav-link" href="https://codelabs.developers.google.com/codelabs/admob-ads-in-flutter" target="_blank" rel="noopener">Add AdMob ads to your Flutter app</a></li><li class="nav-item"><a class="nav-link" href="https://codelabs.developers.google.com/codelabs/admob-inline-ads-in-flutter" target="_blank" rel="noopener">Add an AdMob banner and native inline ads</a></li><li class="nav-item"><a class="nav-link" href="https://developers.google.com/admob/flutter/mediation" target="_blank" rel="noopener">Google AdMob mediation</a></li><li class="nav-item"><a class="nav-link" href="https://pub.dev/packages/interactive_media_ads" target="_blank" rel="noopener">Interactive Media Ads SDK</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-5-4-2" href="#header-sidenav-5-4-2" role="button" aria-expanded="false" aria-controls="header-sidenav-5-4-2">In-app purchases</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-5-4-2"><li class="nav-item"><a class="nav-link" href="/resources/in-app-purchases-overview">In-app purchases overview</a></li><li class="nav-item"><a class="nav-link" href="https://codelabs.developers.google.com/codelabs/flutter-in-app-purchases" target="_blank" rel="noopener">Add in-app purchases</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-5-4-3" href="#header-sidenav-5-4-3" role="button" aria-expanded="false" aria-controls="header-sidenav-5-4-3">Payments</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-5-4-3"><li class="nav-item"><a class="nav-link" href="/resources/payments-overview">Payments overview</a></li><li class="nav-item"><a class="nav-link" href="https://pub.dev/packages/pay" target="_blank" rel="noopener">Google pay package</a></li></ul></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-5-5" href="#header-sidenav-5-5" role="button" aria-expanded="false" aria-controls="header-sidenav-5-5">Maps</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-5-5"><li class="nav-item"><a class="nav-link" href="https://codelabs.developers.google.com/codelabs/google-maps-in-flutter" target="_blank" rel="noopener">Add Google maps to a Flutter app</a></li><li class="nav-item"><a class="nav-link" href="https://developers.google.com/maps/flutter-package" target="_blank" rel="noopener">Google Maps package</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-5-6" href="#header-sidenav-5-6" role="button" aria-expanded="false" aria-controls="header-sidenav-5-6">News</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-5-6"><li class="nav-item"><a class="nav-link" href="/resources/news-toolkit">Build a news app</a></li></ul></li></ul></li><li aria-hidden="true"><div class="sidebar-primary-divider"></div></li><li class="nav-header">User interface</li><li class="nav-item"><a class="nav-link" href="/ui">Introduction</a></li><li class="nav-item"><a class="nav-link" href="/ui/widgets">Widget catalog</a></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#header-sidenav-10" role="button" aria-expanded="false" aria-controls="header-sidenav-10">Layout</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-10"><li class="nav-item"><a class="nav-link" href="/ui/layout">Introduction</a></li><li class="nav-item"><a class="nav-link" href="/ui/layout/tutorial">Build a layout</a></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-10-3" href="/ui/layout/lists" role="button" aria-expanded="false" aria-controls="header-sidenav-10-3">Lists & grids</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-10-3"><li class="nav-item"><a class="nav-link" href="/cookbook/lists/basic-list">Create and use lists</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/lists/horizontal-list">Create a horizontal list</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/lists/grid-lists">Create a grid view</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/lists/mixed-list">Create lists with different types of items</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/lists/spaced-items">Create lists with spaced items</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/lists/long-lists">Work with long lists</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-10-4" href="/ui/layout/scrolling" role="button" aria-expanded="false" aria-controls="header-sidenav-10-4">Scrolling</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-10-4"><li class="nav-item"><a class="nav-link" href="/ui/layout/scrolling">Overview</a></li><li class="nav-item"><a class="nav-link" href="/ui/layout/scrolling/slivers">Use slivers to achieve fancy scrolling</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/lists/floating-app-bar">Place a floating app bar above a list</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/effects/parallax-scrolling">Create a scrolling parallax effect</a></li></ul></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#header-sidenav-11" role="button" aria-expanded="false" aria-controls="header-sidenav-11">Adaptive & responsive design</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-11"><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive">Overview</a></li><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive/general">General approach</a></li><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive/safearea-mediaquery">SafeArea & MediaQuery</a></li><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive/large-screens">Large screens & foldables</a></li><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive/input">User input & accessibility</a></li><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive/capabilities">Capabilities & policies</a></li><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive/best-practices">Best practices</a></li><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive/more-info">Additional resources</a></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#header-sidenav-12" role="button" aria-expanded="false" aria-controls="header-sidenav-12">Design & theming</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-12"><li class="nav-item"><a class="nav-link" href="/cookbook/design/themes">Share styles with themes</a></li><li class="nav-item"><a class="nav-link" href="/ui/design/material">Material design</a></li><li class="nav-item"><a class="nav-link" href="/release/breaking-changes/material-3-migration">Migrate to Material 3</a></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-12-4" href="/ui/design/text" role="button" aria-expanded="false" aria-controls="header-sidenav-12-4">Text</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-12-4"><li class="nav-item"><a class="nav-link" href="/ui/design/text/typography">Fonts & typography</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/design/fonts">Use a custom font</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/design/package-fonts">Export fonts from a package</a></li><li class="nav-item"><a class="nav-link" href="https://pub.dev/packages/google_fonts" target="_blank" rel="noopener">Google Fonts package</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-12-5" href="/ui/design/graphics" role="button" aria-expanded="false" aria-controls="header-sidenav-12-5">Custom graphics</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-12-5"><li class="nav-item"><a class="nav-link" href="/ui/design/graphics/fragment-shaders">Use custom fragment shaders</a></li></ul></li></ul></li><li class="nav-item"><a class="nav-link active collapsible" data-toggle="collapse" href="#header-sidenav-13" role="button" aria-expanded="true" aria-controls="header-sidenav-13">Interactivity</a><ul class="nav flex-column flex-nowrap collapse show" id="header-sidenav-13"><li class="nav-item"><a class="nav-link active" href="/ui/interactivity">Add interactivity to your app</a></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-13-2" href="/ui/interactivity/gestures" role="button" aria-expanded="false" aria-controls="header-sidenav-13-2">Gestures</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-13-2"><li class="nav-item"><a class="nav-link" href="/ui/interactivity/gestures">Introduction</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/gestures/handling-taps">Handle taps</a></li><li class="nav-item"><a class="nav-link" href="/ui/interactivity/gestures/drag-outside">Drag an object outside an app</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/effects/drag-a-widget">Drag a UI element within an app</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/gestures/ripples">Add Material touch ripples</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/gestures/dismissible">Implement swipe to dismiss</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-13-3" href="/ui/interactivity/input" role="button" aria-expanded="false" aria-controls="header-sidenav-13-3">Input & forms</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-13-3"><li class="nav-item"><a class="nav-link" href="/cookbook/forms/text-input">Create and style a text field</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/forms/retrieve-input">Retrieve the value of a text field</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/forms/text-field-changes">Handle changes to a text field</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/forms/focus">Manage focus in text fields</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/forms/validation">Build a form with validation</a></li></ul></li><li class="nav-item"><a class="nav-link" href="/cookbook/design/snackbars">Display a snackbar</a></li><li class="nav-item"><a class="nav-link" href="/ui/interactivity/actions-and-shortcuts">Implement actions & shortcuts</a></li><li class="nav-item"><a class="nav-link" href="/ui/interactivity/focus">Manage keyboard focus</a></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#header-sidenav-14" role="button" aria-expanded="false" aria-controls="header-sidenav-14">Assets & media</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-14"><li class="nav-item"><a class="nav-link" href="/ui/assets/assets-and-images">Add assets and images</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/images/network-image">Display images from the internet</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/images/fading-in-images">Fade in images with a placeholder</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/plugins/play-video">Play and pause a video</a></li><li class="nav-item"><a class="nav-link" href="/ui/assets/asset-transformation">Transform assets at build time</a></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#header-sidenav-15" role="button" aria-expanded="false" aria-controls="header-sidenav-15">Navigation & routing</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-15"><li class="nav-item"><a class="nav-link" href="/ui/navigation">Overview</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/design/tabs">Add tabs to your app</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/navigation/navigation-basics">Navigate to a new screen and back</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/navigation/passing-data">Send data to a new screen</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/navigation/returning-data">Return data from a screen</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/design/drawer">Add a drawer to a screen</a></li><li class="nav-item"><a class="nav-link" href="/ui/navigation/deep-linking">Set up deep linking</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/navigation/set-up-app-links">Set up app links for Android</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/navigation/set-up-universal-links">Set up universal links for iOS</a></li><li class="nav-item"><a class="nav-link" href="/ui/navigation/url-strategies">Configure web URL strategies</a></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#header-sidenav-16" role="button" aria-expanded="false" aria-controls="header-sidenav-16">Animations & transitions</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-16"><li class="nav-item"><a class="nav-link" href="/ui/animations">Introduction</a></li><li class="nav-item"><a class="nav-link" href="/ui/animations/tutorial">Tutorial</a></li><li class="nav-item"><a class="nav-link" href="/ui/animations/implicit-animations">Implicit animations</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/animation/animated-container">Animate the properties of a container</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/animation/opacity-animation">Fade a widget in and out</a></li><li class="nav-item"><a class="nav-link" href="/ui/animations/hero-animations">Hero animations</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/animation/page-route-animation">Animate a page route transition</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/animation/physics-simulation">Animate using a physics simulation</a></li><li class="nav-item"><a class="nav-link" href="/ui/animations/staggered-animations">Staggered animations</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/effects/staggered-menu-animation">Create a staggered menu animation</a></li><li class="nav-item"><a class="nav-link" href="/ui/animations/overview">API overview</a></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#header-sidenav-17" role="button" aria-expanded="false" aria-controls="header-sidenav-17">Accessibility & internationalization</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-17"><li class="nav-item"><a class="nav-link" href="/ui/accessibility-and-internationalization/accessibility">Accessibility</a></li><li class="nav-item"><a class="nav-link" href="/ui/accessibility-and-internationalization/internationalization">Internationalization</a></li></ul></li><li aria-hidden="true"><div class="sidebar-primary-divider"></div></li><li class="nav-header">Beyond UI</li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#header-sidenav-20" role="button" aria-expanded="false" aria-controls="header-sidenav-20">Data & backend</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-20"><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-20-1" href="/data-and-backend/state-mgmt" role="button" aria-expanded="false" aria-controls="header-sidenav-20-1">State management</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-20-1"><li class="nav-item"><a class="nav-link" href="/data-and-backend/state-mgmt/intro">Introduction</a></li><li class="nav-item"><a class="nav-link" href="/data-and-backend/state-mgmt/declarative">Think declaratively</a></li><li class="nav-item"><a class="nav-link" href="/data-and-backend/state-mgmt/ephemeral-vs-app">Ephemeral vs app state</a></li><li class="nav-item"><a class="nav-link" href="/data-and-backend/state-mgmt/simple">Simple app state management</a></li><li class="nav-item"><a class="nav-link" href="/data-and-backend/state-mgmt/options">Options</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-20-2" href="/data-and-backend/networking" role="button" aria-expanded="false" aria-controls="header-sidenav-20-2">Networking & http</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-20-2"><li class="nav-item"><a class="nav-link" href="/data-and-backend/networking">Overview</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/networking/fetch-data">Fetch data from the internet</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/networking/authenticated-requests">Make authenticated requests</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/networking/send-data">Send data to the internet</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/networking/update-data">Update data over the internet</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/networking/delete-data">Delete data on the internet</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/networking/web-sockets">Communicate with WebSockets</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-20-3" href="/data-and-backend/serialization" role="button" aria-expanded="false" aria-controls="header-sidenav-20-3">Serialization</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-20-3"><li class="nav-item"><a class="nav-link" href="/data-and-backend/serialization/json">JSON serialization</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/networking/background-parsing">Parse JSON in the background</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-20-4" href="/data-and-backend/persistence" role="button" aria-expanded="false" aria-controls="header-sidenav-20-4">Persistence</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-20-4"><li class="nav-item"><a class="nav-link" href="/cookbook/persistence/key-value">Store key-value data on disk</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/persistence/reading-writing-files">Read and write files</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/persistence/sqlite">Persist data with SQLite</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-20-5" href="/data-and-backend/firebase" role="button" aria-expanded="false" aria-controls="header-sidenav-20-5">Firebase</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-20-5"><li class="nav-item"><a class="nav-link" href="/data-and-backend/firebase">Overview</a></li><li class="nav-item"><a class="nav-link" href="https://firebase.google.com/docs/flutter/setup" target="_blank" rel="noopener">Add Firebase to your Flutter app</a></li></ul></li><li class="nav-item"><a class="nav-link" href="/data-and-backend/google-apis">Google APIs</a></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#header-sidenav-21" role="button" aria-expanded="false" aria-controls="header-sidenav-21">App architecture</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-21"><li class="nav-item"><a class="nav-link" href="/app-architecture">Introduction</a></li><li class="nav-item"><a class="nav-link" href="/app-architecture/concepts">Architecture concepts</a></li><li class="nav-item"><a class="nav-link" href="/app-architecture/guide">Guide to app architecture</a></li><li class="nav-item"><a class="nav-link" href="/app-architecture/recommendations">Recommendations</a></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-21-5" href="/cookbook/architecture" role="button" aria-expanded="false" aria-controls="header-sidenav-21-5">Design patterns</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-21-5"><li class="nav-item"><a class="nav-link" href="/cookbook/architecture/optimistic-state">Optimistic state</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/architecture/key-value-data">Persistent storage architecture: Key-value data</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/architecture/sql">Persistent storage architecture: SQL</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/architecture/offline-first">Offline-first</a></li></ul></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#header-sidenav-22" role="button" aria-expanded="false" aria-controls="header-sidenav-22">Platform integration</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-22"><li class="nav-item"><a class="nav-link" href="/reference/supported-platforms">Supported platforms</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/desktop">Build desktop apps with Flutter</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/platform-channels">Write platform-specific code</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/platform-adaptations">Automatic platform adaptations</a></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-22-5" href="/platform-integration/android" role="button" aria-expanded="false" aria-controls="header-sidenav-22-5">Android</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-22-5"><li class="nav-item"><a class="nav-link" href="/platform-integration/android/install-android">Add Android as build target</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/splash-screen">Add a splash screen</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/predictive-back">Add predictive back</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/c-interop">Bind to native code</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/platform-views">Host a native Android view</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/call-jetpack-apis">Calling JetPack APIs</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/compose-activity">Launch a Jetpack Compose activity</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/restore-state-android">Restore state on Android</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/chromeos">Target ChromeOS with Android</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-22-6" href="/platform-integration/ios" role="button" aria-expanded="false" aria-controls="header-sidenav-22-6">iOS</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-22-6"><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/install-ios">Add iOS as build target</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/ios-latest">Flutter on latest iOS</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/apple-frameworks">Leverage Apple's system libraries</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/launch-screen">Add a launch screen</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/ios-app-clip">Add iOS App Clip support</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/app-extensions">Add iOS app extensions</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/c-interop">Bind to native code</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/platform-views">Host a native iOS view</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/ios-debugging">Enable debugging on iOS</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/restore-state-ios">Restore state on iOS</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-22-7" href="/platform-integration/linux" role="button" aria-expanded="false" aria-controls="header-sidenav-22-7">Linux</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-22-7"><li class="nav-item"><a class="nav-link" href="/platform-integration/linux/install-linux">Add Linux as build target</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/linux/building">Build a Linux app</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-22-8" href="/platform-integration/macos" role="button" aria-expanded="false" aria-controls="header-sidenav-22-8">macOS</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-22-8"><li class="nav-item"><a class="nav-link" href="/platform-integration/macos/install-macos">Add macOS as build target</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/macos/building">Build a macOS app</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/macos/c-interop">Bind to native code</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/macos/platform-views">Host a native macOS view</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-22-9" href="/platform-integration/web" role="button" aria-expanded="false" aria-controls="header-sidenav-22-9">Web</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-22-9"><li class="nav-item"><a class="nav-link" href="/platform-integration/web">Web support in Flutter</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/install-web">Add web as build target</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/building">Build a web app</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/wasm">Compile to WebAssembly</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/initialization">Customize app initialization</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/embedding-flutter-web">Add Flutter to any web app</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/web-content-in-flutter">Web content in Flutter</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/renderers">Web renderers</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/web-images">Display images on the web</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/faq">Web FAQ</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-22-10" href="/platform-integration/windows" role="button" aria-expanded="false" aria-controls="header-sidenav-22-10">Windows</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-22-10"><li class="nav-item"><a class="nav-link" href="/platform-integration/windows/install-windows">Add Windows as build target</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/windows/building">Build a Windows app</a></li></ul></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#header-sidenav-23" role="button" aria-expanded="false" aria-controls="header-sidenav-23">Packages & plugins</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-23"><li class="nav-item"><a class="nav-link" href="/packages-and-plugins/using-packages">Use packages & plugins</a></li><li class="nav-item"><a class="nav-link" href="/packages-and-plugins/developing-packages">Develop packages & plugins</a></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-23-3" href="/packages-and-plugins/swift-package-manager" role="button" aria-expanded="false" aria-controls="header-sidenav-23-3">Swift Package Manager</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-23-3"><li class="nav-item"><a class="nav-link" href="/packages-and-plugins/swift-package-manager/for-app-developers">For app developers</a></li><li class="nav-item"><a class="nav-link" href="/packages-and-plugins/swift-package-manager/for-plugin-authors">For plugin authors</a></li></ul></li><div class="dropdown-divider"></div><li class="nav-item"><a class="nav-link" href="/packages-and-plugins/favorites">Flutter Favorites</a></li><li class="nav-item"><a class="nav-link" href="https://pub.dev/flutter" target="_blank" rel="noopener">Package repository</a></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#header-sidenav-24" role="button" aria-expanded="false" aria-controls="header-sidenav-24">Testing & debugging</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-24"><li class="nav-header">Testing</li><li class="nav-item"><a class="nav-link" href="/testing/overview">Overview</a></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-24-3" href="#header-sidenav-24-3" role="button" aria-expanded="false" aria-controls="header-sidenav-24-3">Unit testing</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-24-3"><li class="nav-item"><a class="nav-link" href="/cookbook/testing/unit/introduction">Introduction</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/testing/unit/mocking">Mock dependencies</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-24-4" href="#header-sidenav-24-4" role="button" aria-expanded="false" aria-controls="header-sidenav-24-4">Widget testing</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-24-4"><li class="nav-item"><a class="nav-link" href="/cookbook/testing/widget/introduction">Introduction</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/testing/widget/finders">Find widgets</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/testing/widget/scrolling">Simulate scrolling</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/testing/widget/tap-drag">Simulate user interaction</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-24-5" href="#header-sidenav-24-5" role="button" aria-expanded="false" aria-controls="header-sidenav-24-5">Integration testing</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-24-5"><li class="nav-item"><a class="nav-link" href="/cookbook/testing/integration/introduction">Introduction</a></li><li class="nav-item"><a class="nav-link" href="/testing/integration-tests">Write and run an integration test</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/testing/integration/profiling">Profile an integration test</a></li></ul></li><li class="nav-item"><a class="nav-link" href="/testing/testing-plugins">Test a plugin</a></li><li class="nav-item"><a class="nav-link" href="/testing/plugins-in-tests">Handle plugin code in tests</a></li><li class="nav-header">Debugging</li><li class="nav-item"><a class="nav-link" href="/testing/debugging">Debugging tools</a></li><li class="nav-item"><a class="nav-link" href="/testing/code-debugging">Debug your app programmatically</a></li><li class="nav-item"><a class="nav-link" href="/testing/native-debugging">Use a native language debugger</a></li><li class="nav-item"><a class="nav-link" href="/testing/build-modes">Flutter's build modes</a></li><li class="nav-item"><a class="nav-link" href="/testing/common-errors">Common Flutter errors</a></li><li class="nav-item"><a class="nav-link" href="/testing/errors">Handle errors</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/maintenance/error-reporting">Report errors to a service</a></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#header-sidenav-25" role="button" aria-expanded="false" aria-controls="header-sidenav-25">Performance & optimization</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-25"><li class="nav-item"><a class="nav-link" href="/perf">Overview</a></li><li class="nav-item"><a class="nav-link" href="/perf/impeller">Impeller</a></li><li class="nav-item"><a class="nav-link" href="/perf/best-practices">Performance best practices</a></li><li class="nav-item"><a class="nav-link" href="/perf/app-size">App size</a></li><li class="nav-item"><a class="nav-link" href="/perf/deferred-components">Deferred components</a></li><li class="nav-item"><a class="nav-link" href="/perf/rendering-performance">Rendering performance</a></li><li class="nav-item"><a class="nav-link" href="/perf/ui-performance">Performance profiling</a></li><li class="nav-item"><a class="nav-link" href="/perf/web-performance">Performance profiling for web</a></li><li class="nav-item"><a class="nav-link" href="/perf/shader">Shader compilation jank</a></li><li class="nav-item"><a class="nav-link" href="/perf/metrics">Performance metrics</a></li><li class="nav-item"><a class="nav-link" href="/perf/isolates">Concurrency and isolates</a></li><li class="nav-item"><a class="nav-link" href="/perf/faq">Performance FAQ</a></li><li class="nav-item"><a class="nav-link" href="/perf/appendix">Appendix</a></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#header-sidenav-26" role="button" aria-expanded="false" aria-controls="header-sidenav-26">Deployment</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-26"><li class="nav-item"><a class="nav-link" href="/deployment/obfuscate">Obfuscate Dart code</a></li><li class="nav-item"><a class="nav-link" href="/deployment/flavors">Create flavors of an app</a></li><li class="nav-item"><a class="nav-link" href="/deployment/android">Build and release an Android app</a></li><li class="nav-item"><a class="nav-link" href="/deployment/ios">Build and release an iOS app</a></li><li class="nav-item"><a class="nav-link" href="/deployment/macos">Build and release a macOS app</a></li><li class="nav-item"><a class="nav-link" href="/deployment/linux">Build and release a Linux app</a></li><li class="nav-item"><a class="nav-link" href="/deployment/windows">Build and release a Windows app</a></li><li class="nav-item"><a class="nav-link" href="/deployment/web">Build and release a web app</a></li><li class="nav-item"><a class="nav-link" href="/deployment/cd">Set up continuous deployment</a></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#header-sidenav-27" role="button" aria-expanded="false" aria-controls="header-sidenav-27">Add to an existing app</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-27"><li class="nav-item"><a class="nav-link" href="/add-to-app">Introduction</a></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-27-2" href="/add-to-app/android" role="button" aria-expanded="false" aria-controls="header-sidenav-27-2">Add to an Android app</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-27-2"><li class="nav-item"><a class="nav-link" href="/add-to-app/android/project-setup">Set up Android project</a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/android/add-flutter-screen">Add a single Flutter screen</a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/android/add-flutter-fragment">Add a Flutter Fragment</a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/android/add-flutter-view">Add a Flutter View</a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/android/plugin-setup">Use a Flutter plugin</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-27-3" href="/add-to-app/ios" role="button" aria-expanded="false" aria-controls="header-sidenav-27-3">Add to an iOS app</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-27-3"><li class="nav-item"><a class="nav-link" href="/add-to-app/ios/project-setup">Set up iOS project</a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/ios/add-flutter-screen">Add a single Flutter screen</a></li></ul></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/embedding-flutter-web">Add to a web app</a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/debugging">Debug embedded Flutter module</a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/multiple-flutters">Add multiple Flutter instances</a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/performance">Loading sequence and performance</a></li></ul></li><li aria-hidden="true"><div class="sidebar-primary-divider"></div></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#header-sidenav-29" role="button" aria-expanded="false" aria-controls="header-sidenav-29">Tools & editors</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-29"><li class="nav-item"><a class="nav-link" href="/tools/android-studio">Android Studio & IntelliJ</a></li><li class="nav-item"><a class="nav-link" href="/tools/vs-code">Visual Studio Code</a></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-29-3" href="/tools/devtools" role="button" aria-expanded="false" aria-controls="header-sidenav-29-3">DevTools</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-29-3"><li class="nav-item"><a class="nav-link" href="/tools/devtools">Overview</a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/android-studio">Run from Android Studio & IntelliJ</a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/vscode">Run from VS Code</a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/cli">Run from command line</a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/inspector">Flutter inspector</a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/performance">Performance view</a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/cpu-profiler">CPU Profiler view</a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/memory">Memory view</a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/console">Debug console view</a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/network">Network view</a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/debugger">Debugger</a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/logging">Logging view</a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/app-size">App size tool</a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/extensions">DevTools extensions</a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/deep-links">Validate deep links</a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/release-notes">Release notes</a></li></ul></li><li class="nav-item"><a class="nav-link" href="/tools/sdk">SDK overview</a></li><li class="nav-item"><a class="nav-link" href="/tools/pubspec">Flutter's pubspec options</a></li><li class="nav-item"><a class="nav-link" href="/tools/flutter-fix">Automated fixes</a></li><li class="nav-item"><a class="nav-link" href="/tools/formatting">Code formatting</a></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#header-sidenav-30" role="button" aria-expanded="false" aria-controls="header-sidenav-30">Flutter concepts</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-30"><li class="nav-item"><a class="nav-link" href="/resources/architectural-overview">Architectural overview</a></li><li class="nav-item"><a class="nav-link" href="/resources/inside-flutter">Inside Flutter</a></li><li class="nav-item"><a class="nav-link" href="/ui/layout/constraints">Understanding constraints</a></li><li class="nav-item"><a class="nav-link" href="/testing/build-modes">Flutter's build modes</a></li><li class="nav-item"><a class="nav-link" href="/tools/hot-reload">Hot reload</a></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#header-sidenav-31" role="button" aria-expanded="false" aria-controls="header-sidenav-31">Resources</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-31"><li class="nav-item"><a class="nav-link" href="/resources/faq">FAQ</a></li><li class="nav-item"><a class="nav-link" href="/resources/books">Books</a></li><li class="nav-item"><a class="nav-link" href="/resources/videos">Videos</a></li><li class="nav-item"><a class="nav-link" href="/resources/courses">Courses</a></li><li class="nav-item"><a class="nav-link" href="/resources/bootstrap-into-dart">Learn Dart</a></li><li class="nav-item"><a class="nav-link" href="/resources/support">Get support</a></li><div class="dropdown-divider"></div><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-31-8" href="#header-sidenav-31-8" role="button" aria-expanded="false" aria-controls="header-sidenav-31-8">Contribute</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-31-8"><li class="nav-item"><a class="nav-link" href="/resources/bug-reports">Create useful bug reports</a></li><li class="nav-item"><a class="nav-link" href="https://github.com/flutter/flutter/blob/main/CONTRIBUTING.md" target="_blank" rel="noopener">Contribute to Flutter</a></li><li class="nav-item"><a class="nav-link" href="/resources/design-docs">Discover proposed features</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#header-sidenav-31-9" href="/reference" role="button" aria-expanded="false" aria-controls="header-sidenav-31-9">Reference</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-31-9"><li class="nav-item"><a class="nav-link" href="/dash">Who is Dash?</a></li><li class="nav-item"><a class="nav-link" href="/reference/widgets">Widget index</a></li><li class="nav-item"><a class="nav-link" href="/reference/flutter-cli">flutter CLI</a></li><li class="nav-item"><a class="nav-link" href="https://api.flutter.dev" target="_blank" rel="noopener">API docs</a></li></ul></li></ul></li></ul></div><li class="nav-item dropdown"><a class="nav-link dropdown-toggle" id="platform-navbar-dropdown" href="https://flutter.dev/multi-platform" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Multi-Platform</a><div class="dropdown-menu" aria-labelledby="platform-navbar-dropdown"><a class="dropdown-item" href="https://flutter.dev/multi-platform/mobile">Mobile</a> <a class="dropdown-item" href="https://flutter.dev/multi-platform/web">Web</a> <a class="dropdown-item" href="https://flutter.dev/multi-platform/desktop">Desktop</a> <a class="dropdown-item" href="https://flutter.dev/multi-platform/embedded">Embedded</a></div></li><li class="nav-item dropdown"><a class="nav-link dropdown-toggle" id="dev-navbar-dropdown" href="https://flutter.dev/" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Development</a><div class="dropdown-menu" aria-labelledby="dev-navbar-dropdown"><a class="dropdown-item" href="https://flutter.dev/learn">Learn</a> <a class="dropdown-item" href="https://pub.dev/flutter/favorites" target="_blank">Flutter Favorites</a> <a class="dropdown-item" href="https://pub.dev/" target="_blank">Packages</a> <a class="dropdown-item" href="https://flutter.dev/monetization">Monetization</a> <a class="dropdown-item" href="https://flutter.dev/games">Games</a> <a class="dropdown-item" href="https://flutter.dev/news">News</a></div></li><li class="nav-item dropdown"><a class="nav-link dropdown-toggle" id="ecosystem-navbar-dropdown" href="https://flutter.dev/ecosystem" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Ecosystem</a><div class="dropdown-menu" aria-labelledby="ecosystem-navbar-dropdown"><a class="dropdown-item" href="https://flutter.dev/community">Community</a> <a class="dropdown-item" href="https://flutter.dev/events">Events</a> <a class="dropdown-item" href="https://flutter.dev/culture">Culture</a></div></li><li class="nav-item"><a class="nav-link" href="https://flutter.dev/showcase">Showcase</a></li><li class="nav-item dropdown docs-item"><a class="nav-link dropdown-toggle" id="docs-navbar-dropdown" href="/" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Docs</a><div class="dropdown-menu" aria-labelledby="docs-navbar-dropdown"><a class="dropdown-item" href="/release/whats-new">What's new</a> <a class="dropdown-item" href="/get-started/editor">Editor support</a> <a class="dropdown-item" href="/tools/hot-reload">Hot reload</a> <a class="dropdown-item" href="/perf/ui-performance">Profiling</a> <a class="dropdown-item" href="/get-started/install">Install Flutter</a> <a class="dropdown-item" href="/tools/devtools">DevTools</a> <a class="dropdown-item" href="/cookbook">Cookbook</a> <a class="dropdown-item" href="/codelabs">Codelabs</a></div></li></ul><form action="/search/" class="site-header__search form-inline"><input class="site-header__searchfield form-control search-field" type="search" name="q" id="q" autocomplete="off" placeholder="Search" aria-label="Search"></form></div></div><div class="site-header__social navbar-nav flex-row"><a class="nav-item nav-link nav-icon" href="https://twitter.com/FlutterDev" aria-label="Open Flutter's X (Twitter) in a new tab" target="_blank" rel="noreferrer"><svg><use href="/assets/images/social/x.svg#x"></use></svg> </a><a class="nav-item nav-link nav-icon" href="https://www.youtube.com/@flutterdev" aria-label="Open Flutter's YouTube in a new tab" target="_blank" rel="noreferrer"><svg><use href="/assets/images/social/youtube.svg#youtube"></use></svg> </a><a class="nav-item nav-link nav-icon" href="https://medium.com/flutter" aria-label="Open Flutter's Medium blog in a new tab" target="_blank" rel="noreferrer"><svg><use href="/assets/images/social/medium.svg#medium"></use></svg> </a><a class="nav-item nav-link nav-icon" href="https://github.com/flutter" aria-label="Open Flutter's GitHub in a new tab" target="_blank" rel="noreferrer"><svg><use href="/assets/images/social/github.svg#github"></use></svg></a></div><a class="site-header__cta btn btn-primary" href="/get-started/install/">Get started</a></nav></header><div class="site-banner site-banner--default" role="alert"><a href="https://medium.com/flutter/flutter-3-24-dart-3-5-204b7d20c45d">Flutter 3.24 and Dart 3.5</a> are here! Check out <a href="/release/whats-new">what's new</a> on the website.</div><div class="container-fluid position-relative"><div class="row flex-xl-nowrap"><div class="fixed-col site-sidebar site-sidebar--fixed col-12 col-md-3 col-xl-2 d-none d-md-block" data-fixed-column><ul class="nav flex-column"><li class="nav-header">Get started</li><li class="nav-item"><a class="nav-link" href="/get-started/install">Set up Flutter</a></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#fixed-sidenav-3" role="button" aria-expanded="false" aria-controls="fixed-sidenav-3">Learn Flutter</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-3"><li class="nav-item"><a class="nav-link" href="/get-started/learn-flutter">Introduction</a></li><li class="nav-item"><a class="nav-link" href="/get-started/codelab">Write your first app</a></li><li class="nav-item"><a class="nav-link collapsible" data-toggle="collapse" data-target="#fixed-sidenav-3-3" href="#fixed-sidenav-3-3" role="button" aria-expanded="true" aria-controls="fixed-sidenav-3-3">Learn the fundamentals</a><ul class="nav flex-column flex-nowrap collapse show" id="fixed-sidenav-3-3"><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals">Introduction</a></li><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals/dart">Intro to Dart</a></li><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals/widgets">Widgets</a></li><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals/layout">Layout</a></li><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals/state-management">State management</a></li><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals/user-input">Handling user input</a></li><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals/networking">Networking and data</a></li><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals/local-caching">Local data and caching</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-3-4" href="/get-started/flutter-for" role="button" aria-expanded="false" aria-controls="fixed-sidenav-3-4">From another platform?</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-3-4"><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/android-devs">Flutter for Android devs</a></li><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/swiftui-devs">Flutter for SwiftUI devs</a></li><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/uikit-devs">Flutter for UIKit devs</a></li><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/react-native-devs">Flutter for React Native devs</a></li><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/web-devs">Flutter for web devs</a></li><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/xamarin-forms-devs">Flutter for Xamarin.Forms devs</a></li><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/declarative">Introduction to declarative UI</a></li><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/dart-swift-concurrency">Flutter versus Swift concurrency</a></li></ul></li><div class="dropdown-divider"></div><li class="nav-item"><a class="nav-link" href="/codelabs">Codelabs</a></li><li class="nav-item"><a class="nav-link" href="/cookbook">Cookbook</a></li><li class="nav-item"><a class="nav-link" href="https://flutter.github.io/samples/" target="_blank" rel="noopener">Demos and samples</a></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#fixed-sidenav-4" role="button" aria-expanded="false" aria-controls="fixed-sidenav-4">Stay up to date</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-4"><li class="nav-item"><a class="nav-link" href="/release/upgrade">Upgrade</a></li><li class="nav-item"><a class="nav-link" href="/release/archive">SDK archive</a></li><div class="dropdown-divider"></div><li class="nav-item"><a class="nav-link" href="/release/whats-new">What's new</a></li><li class="nav-item"><a class="nav-link" href="/release/release-notes">Release notes</a></li><li class="nav-item"><a class="nav-link" href="/release/breaking-changes">Breaking changes</a></li><li class="nav-item"><a class="nav-link" href="/release/compatibility-policy">Compatibility policy</a></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#fixed-sidenav-5" role="button" aria-expanded="false" aria-controls="fixed-sidenav-5">App solutions</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-5"><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-5-1" href="#fixed-sidenav-5-1" role="button" aria-expanded="false" aria-controls="fixed-sidenav-5-1">AI</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-5-1"><li class="nav-item"><a class="nav-link" href="/resources/ai-overview">Overview</a></li><li class="nav-item"><a class="nav-link" href="https://ai.google.dev/gemini-api/docs/get-started/dart" target="_blank" rel="noopener">Get started with the Gemini API</a></li><li class="nav-item"><a class="nav-link" href="https://pub.dev/packages/google_generative_ai" target="_blank" rel="noopener">Google AI Dart SDK (pub.dev)</a></li><li class="nav-item"><a class="nav-link" href="https://www.youtube.com/watch?v=1AuzJEiHjO4" target="_blank" rel="noopener">Build with Google AI Dart SDK (video)</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-5-2" href="#fixed-sidenav-5-2" role="button" aria-expanded="false" aria-controls="fixed-sidenav-5-2">Firebase & Firestore</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-5-2"><li class="nav-item"><a class="nav-link" href="/data-and-backend/firebase">Overview</a></li><li class="nav-item"><a class="nav-link" href="https://firebase.google.com/docs/flutter" target="_blank" rel="noopener">Discover Firebase for Flutter</a></li><li class="nav-item"><a class="nav-link" href="https://www.youtube.com/watch?v=wUSkeTaBonA" target="_blank" rel="noopener">Get to know Firebase for Flutter</a></li><li class="nav-item"><a class="nav-link" href="https://firebase.google.com/codelabs/firebase-auth-in-flutter-apps" target="_blank" rel="noopener">Add a user authentication flow to a Flutter app using FirebaseUI</a></li><li class="nav-item"><a class="nav-link" href="https://firebase.google.com/codelabs/firebase-get-to-know-web" target="_blank" rel="noopener">Get to know Firebase for web</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-5-3" href="#fixed-sidenav-5-3" role="button" aria-expanded="false" aria-controls="fixed-sidenav-5-3">Games</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-5-3"><li class="nav-item"><a class="nav-link" href="/resources/games-toolkit">Overview</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/games/achievements-leaderboard">Add achievements and leaderboards</a></li><li class="nav-item"><a class="nav-link" href="https://firebase.google.com/codelabs/build-leaderboards-with-firestore#0" target="_blank" rel="noopener">Build leaderboards with Firestore</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/plugins/google-mobile-ads">Add advertising</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/games/firestore-multiplayer">Add multiplayer support</a></li><li class="nav-item"><a class="nav-link" href="https://codelabs.developers.google.com/codelabs/flutter-in-app-purchases" target="_blank" rel="noopener">Add in-app purchases</a></li><li class="nav-item"><a class="nav-link" href="https://firebase.google.com/codelabs/firebase-auth-in-flutter-apps" target="_blank" rel="noopener">Add user authentication</a></li><li class="nav-item"><a class="nav-link" href="https://firebase.google.com/docs/crashlytics/get-started?platform=flutter" target="_blank" rel="noopener">Debug using Crashlytics</a></li><li class="nav-item"><a class="nav-link" href="https://codelabs.developers.google.com/codelabs/flutter-flame-brick-breaker" target="_blank" rel="noopener">Intro to Flame with Flutter</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-5-4" href="#fixed-sidenav-5-4" role="button" aria-expanded="false" aria-controls="fixed-sidenav-5-4">Monetization</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-5-4"><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-5-4-1" href="#fixed-sidenav-5-4-1" role="button" aria-expanded="false" aria-controls="fixed-sidenav-5-4-1">Advertising</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-5-4-1"><li class="nav-item"><a class="nav-link" href="/resources/ads-overview">Ads overview</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/plugins/google-mobile-ads">Add advertising</a></li><li class="nav-item"><a class="nav-link" href="https://codelabs.developers.google.com/codelabs/admob-ads-in-flutter" target="_blank" rel="noopener">Add AdMob ads to your Flutter app</a></li><li class="nav-item"><a class="nav-link" href="https://codelabs.developers.google.com/codelabs/admob-inline-ads-in-flutter" target="_blank" rel="noopener">Add an AdMob banner and native inline ads</a></li><li class="nav-item"><a class="nav-link" href="https://developers.google.com/admob/flutter/mediation" target="_blank" rel="noopener">Google AdMob mediation</a></li><li class="nav-item"><a class="nav-link" href="https://pub.dev/packages/interactive_media_ads" target="_blank" rel="noopener">Interactive Media Ads SDK</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-5-4-2" href="#fixed-sidenav-5-4-2" role="button" aria-expanded="false" aria-controls="fixed-sidenav-5-4-2">In-app purchases</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-5-4-2"><li class="nav-item"><a class="nav-link" href="/resources/in-app-purchases-overview">In-app purchases overview</a></li><li class="nav-item"><a class="nav-link" href="https://codelabs.developers.google.com/codelabs/flutter-in-app-purchases" target="_blank" rel="noopener">Add in-app purchases</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-5-4-3" href="#fixed-sidenav-5-4-3" role="button" aria-expanded="false" aria-controls="fixed-sidenav-5-4-3">Payments</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-5-4-3"><li class="nav-item"><a class="nav-link" href="/resources/payments-overview">Payments overview</a></li><li class="nav-item"><a class="nav-link" href="https://pub.dev/packages/pay" target="_blank" rel="noopener">Google pay package</a></li></ul></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-5-5" href="#fixed-sidenav-5-5" role="button" aria-expanded="false" aria-controls="fixed-sidenav-5-5">Maps</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-5-5"><li class="nav-item"><a class="nav-link" href="https://codelabs.developers.google.com/codelabs/google-maps-in-flutter" target="_blank" rel="noopener">Add Google maps to a Flutter app</a></li><li class="nav-item"><a class="nav-link" href="https://developers.google.com/maps/flutter-package" target="_blank" rel="noopener">Google Maps package</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-5-6" href="#fixed-sidenav-5-6" role="button" aria-expanded="false" aria-controls="fixed-sidenav-5-6">News</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-5-6"><li class="nav-item"><a class="nav-link" href="/resources/news-toolkit">Build a news app</a></li></ul></li></ul></li><li aria-hidden="true"><div class="sidebar-primary-divider"></div></li><li class="nav-header">User interface</li><li class="nav-item"><a class="nav-link" href="/ui">Introduction</a></li><li class="nav-item"><a class="nav-link" href="/ui/widgets">Widget catalog</a></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#fixed-sidenav-10" role="button" aria-expanded="false" aria-controls="fixed-sidenav-10">Layout</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-10"><li class="nav-item"><a class="nav-link" href="/ui/layout">Introduction</a></li><li class="nav-item"><a class="nav-link" href="/ui/layout/tutorial">Build a layout</a></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-10-3" href="/ui/layout/lists" role="button" aria-expanded="false" aria-controls="fixed-sidenav-10-3">Lists & grids</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-10-3"><li class="nav-item"><a class="nav-link" href="/cookbook/lists/basic-list">Create and use lists</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/lists/horizontal-list">Create a horizontal list</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/lists/grid-lists">Create a grid view</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/lists/mixed-list">Create lists with different types of items</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/lists/spaced-items">Create lists with spaced items</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/lists/long-lists">Work with long lists</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-10-4" href="/ui/layout/scrolling" role="button" aria-expanded="false" aria-controls="fixed-sidenav-10-4">Scrolling</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-10-4"><li class="nav-item"><a class="nav-link" href="/ui/layout/scrolling">Overview</a></li><li class="nav-item"><a class="nav-link" href="/ui/layout/scrolling/slivers">Use slivers to achieve fancy scrolling</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/lists/floating-app-bar">Place a floating app bar above a list</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/effects/parallax-scrolling">Create a scrolling parallax effect</a></li></ul></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#fixed-sidenav-11" role="button" aria-expanded="false" aria-controls="fixed-sidenav-11">Adaptive & responsive design</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-11"><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive">Overview</a></li><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive/general">General approach</a></li><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive/safearea-mediaquery">SafeArea & MediaQuery</a></li><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive/large-screens">Large screens & foldables</a></li><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive/input">User input & accessibility</a></li><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive/capabilities">Capabilities & policies</a></li><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive/best-practices">Best practices</a></li><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive/more-info">Additional resources</a></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#fixed-sidenav-12" role="button" aria-expanded="false" aria-controls="fixed-sidenav-12">Design & theming</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-12"><li class="nav-item"><a class="nav-link" href="/cookbook/design/themes">Share styles with themes</a></li><li class="nav-item"><a class="nav-link" href="/ui/design/material">Material design</a></li><li class="nav-item"><a class="nav-link" href="/release/breaking-changes/material-3-migration">Migrate to Material 3</a></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-12-4" href="/ui/design/text" role="button" aria-expanded="false" aria-controls="fixed-sidenav-12-4">Text</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-12-4"><li class="nav-item"><a class="nav-link" href="/ui/design/text/typography">Fonts & typography</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/design/fonts">Use a custom font</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/design/package-fonts">Export fonts from a package</a></li><li class="nav-item"><a class="nav-link" href="https://pub.dev/packages/google_fonts" target="_blank" rel="noopener">Google Fonts package</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-12-5" href="/ui/design/graphics" role="button" aria-expanded="false" aria-controls="fixed-sidenav-12-5">Custom graphics</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-12-5"><li class="nav-item"><a class="nav-link" href="/ui/design/graphics/fragment-shaders">Use custom fragment shaders</a></li></ul></li></ul></li><li class="nav-item"><a class="nav-link active collapsible" data-toggle="collapse" href="#fixed-sidenav-13" role="button" aria-expanded="true" aria-controls="fixed-sidenav-13">Interactivity</a><ul class="nav flex-column flex-nowrap collapse show" id="fixed-sidenav-13"><li class="nav-item"><a class="nav-link active" href="/ui/interactivity">Add interactivity to your app</a></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-13-2" href="/ui/interactivity/gestures" role="button" aria-expanded="false" aria-controls="fixed-sidenav-13-2">Gestures</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-13-2"><li class="nav-item"><a class="nav-link" href="/ui/interactivity/gestures">Introduction</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/gestures/handling-taps">Handle taps</a></li><li class="nav-item"><a class="nav-link" href="/ui/interactivity/gestures/drag-outside">Drag an object outside an app</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/effects/drag-a-widget">Drag a UI element within an app</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/gestures/ripples">Add Material touch ripples</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/gestures/dismissible">Implement swipe to dismiss</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-13-3" href="/ui/interactivity/input" role="button" aria-expanded="false" aria-controls="fixed-sidenav-13-3">Input & forms</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-13-3"><li class="nav-item"><a class="nav-link" href="/cookbook/forms/text-input">Create and style a text field</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/forms/retrieve-input">Retrieve the value of a text field</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/forms/text-field-changes">Handle changes to a text field</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/forms/focus">Manage focus in text fields</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/forms/validation">Build a form with validation</a></li></ul></li><li class="nav-item"><a class="nav-link" href="/cookbook/design/snackbars">Display a snackbar</a></li><li class="nav-item"><a class="nav-link" href="/ui/interactivity/actions-and-shortcuts">Implement actions & shortcuts</a></li><li class="nav-item"><a class="nav-link" href="/ui/interactivity/focus">Manage keyboard focus</a></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#fixed-sidenav-14" role="button" aria-expanded="false" aria-controls="fixed-sidenav-14">Assets & media</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-14"><li class="nav-item"><a class="nav-link" href="/ui/assets/assets-and-images">Add assets and images</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/images/network-image">Display images from the internet</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/images/fading-in-images">Fade in images with a placeholder</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/plugins/play-video">Play and pause a video</a></li><li class="nav-item"><a class="nav-link" href="/ui/assets/asset-transformation">Transform assets at build time</a></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#fixed-sidenav-15" role="button" aria-expanded="false" aria-controls="fixed-sidenav-15">Navigation & routing</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-15"><li class="nav-item"><a class="nav-link" href="/ui/navigation">Overview</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/design/tabs">Add tabs to your app</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/navigation/navigation-basics">Navigate to a new screen and back</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/navigation/passing-data">Send data to a new screen</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/navigation/returning-data">Return data from a screen</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/design/drawer">Add a drawer to a screen</a></li><li class="nav-item"><a class="nav-link" href="/ui/navigation/deep-linking">Set up deep linking</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/navigation/set-up-app-links">Set up app links for Android</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/navigation/set-up-universal-links">Set up universal links for iOS</a></li><li class="nav-item"><a class="nav-link" href="/ui/navigation/url-strategies">Configure web URL strategies</a></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#fixed-sidenav-16" role="button" aria-expanded="false" aria-controls="fixed-sidenav-16">Animations & transitions</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-16"><li class="nav-item"><a class="nav-link" href="/ui/animations">Introduction</a></li><li class="nav-item"><a class="nav-link" href="/ui/animations/tutorial">Tutorial</a></li><li class="nav-item"><a class="nav-link" href="/ui/animations/implicit-animations">Implicit animations</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/animation/animated-container">Animate the properties of a container</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/animation/opacity-animation">Fade a widget in and out</a></li><li class="nav-item"><a class="nav-link" href="/ui/animations/hero-animations">Hero animations</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/animation/page-route-animation">Animate a page route transition</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/animation/physics-simulation">Animate using a physics simulation</a></li><li class="nav-item"><a class="nav-link" href="/ui/animations/staggered-animations">Staggered animations</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/effects/staggered-menu-animation">Create a staggered menu animation</a></li><li class="nav-item"><a class="nav-link" href="/ui/animations/overview">API overview</a></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#fixed-sidenav-17" role="button" aria-expanded="false" aria-controls="fixed-sidenav-17">Accessibility & internationalization</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-17"><li class="nav-item"><a class="nav-link" href="/ui/accessibility-and-internationalization/accessibility">Accessibility</a></li><li class="nav-item"><a class="nav-link" href="/ui/accessibility-and-internationalization/internationalization">Internationalization</a></li></ul></li><li aria-hidden="true"><div class="sidebar-primary-divider"></div></li><li class="nav-header">Beyond UI</li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#fixed-sidenav-20" role="button" aria-expanded="false" aria-controls="fixed-sidenav-20">Data & backend</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-20"><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-20-1" href="/data-and-backend/state-mgmt" role="button" aria-expanded="false" aria-controls="fixed-sidenav-20-1">State management</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-20-1"><li class="nav-item"><a class="nav-link" href="/data-and-backend/state-mgmt/intro">Introduction</a></li><li class="nav-item"><a class="nav-link" href="/data-and-backend/state-mgmt/declarative">Think declaratively</a></li><li class="nav-item"><a class="nav-link" href="/data-and-backend/state-mgmt/ephemeral-vs-app">Ephemeral vs app state</a></li><li class="nav-item"><a class="nav-link" href="/data-and-backend/state-mgmt/simple">Simple app state management</a></li><li class="nav-item"><a class="nav-link" href="/data-and-backend/state-mgmt/options">Options</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-20-2" href="/data-and-backend/networking" role="button" aria-expanded="false" aria-controls="fixed-sidenav-20-2">Networking & http</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-20-2"><li class="nav-item"><a class="nav-link" href="/data-and-backend/networking">Overview</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/networking/fetch-data">Fetch data from the internet</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/networking/authenticated-requests">Make authenticated requests</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/networking/send-data">Send data to the internet</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/networking/update-data">Update data over the internet</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/networking/delete-data">Delete data on the internet</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/networking/web-sockets">Communicate with WebSockets</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-20-3" href="/data-and-backend/serialization" role="button" aria-expanded="false" aria-controls="fixed-sidenav-20-3">Serialization</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-20-3"><li class="nav-item"><a class="nav-link" href="/data-and-backend/serialization/json">JSON serialization</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/networking/background-parsing">Parse JSON in the background</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-20-4" href="/data-and-backend/persistence" role="button" aria-expanded="false" aria-controls="fixed-sidenav-20-4">Persistence</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-20-4"><li class="nav-item"><a class="nav-link" href="/cookbook/persistence/key-value">Store key-value data on disk</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/persistence/reading-writing-files">Read and write files</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/persistence/sqlite">Persist data with SQLite</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-20-5" href="/data-and-backend/firebase" role="button" aria-expanded="false" aria-controls="fixed-sidenav-20-5">Firebase</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-20-5"><li class="nav-item"><a class="nav-link" href="/data-and-backend/firebase">Overview</a></li><li class="nav-item"><a class="nav-link" href="https://firebase.google.com/docs/flutter/setup" target="_blank" rel="noopener">Add Firebase to your Flutter app</a></li></ul></li><li class="nav-item"><a class="nav-link" href="/data-and-backend/google-apis">Google APIs</a></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#fixed-sidenav-21" role="button" aria-expanded="false" aria-controls="fixed-sidenav-21">App architecture</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-21"><li class="nav-item"><a class="nav-link" href="/app-architecture">Introduction</a></li><li class="nav-item"><a class="nav-link" href="/app-architecture/concepts">Architecture concepts</a></li><li class="nav-item"><a class="nav-link" href="/app-architecture/guide">Guide to app architecture</a></li><li class="nav-item"><a class="nav-link" href="/app-architecture/recommendations">Recommendations</a></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-21-5" href="/cookbook/architecture" role="button" aria-expanded="false" aria-controls="fixed-sidenav-21-5">Design patterns</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-21-5"><li class="nav-item"><a class="nav-link" href="/cookbook/architecture/optimistic-state">Optimistic state</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/architecture/key-value-data">Persistent storage architecture: Key-value data</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/architecture/sql">Persistent storage architecture: SQL</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/architecture/offline-first">Offline-first</a></li></ul></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#fixed-sidenav-22" role="button" aria-expanded="false" aria-controls="fixed-sidenav-22">Platform integration</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-22"><li class="nav-item"><a class="nav-link" href="/reference/supported-platforms">Supported platforms</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/desktop">Build desktop apps with Flutter</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/platform-channels">Write platform-specific code</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/platform-adaptations">Automatic platform adaptations</a></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-22-5" href="/platform-integration/android" role="button" aria-expanded="false" aria-controls="fixed-sidenav-22-5">Android</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-22-5"><li class="nav-item"><a class="nav-link" href="/platform-integration/android/install-android">Add Android as build target</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/splash-screen">Add a splash screen</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/predictive-back">Add predictive back</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/c-interop">Bind to native code</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/platform-views">Host a native Android view</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/call-jetpack-apis">Calling JetPack APIs</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/compose-activity">Launch a Jetpack Compose activity</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/restore-state-android">Restore state on Android</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/chromeos">Target ChromeOS with Android</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-22-6" href="/platform-integration/ios" role="button" aria-expanded="false" aria-controls="fixed-sidenav-22-6">iOS</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-22-6"><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/install-ios">Add iOS as build target</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/ios-latest">Flutter on latest iOS</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/apple-frameworks">Leverage Apple's system libraries</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/launch-screen">Add a launch screen</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/ios-app-clip">Add iOS App Clip support</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/app-extensions">Add iOS app extensions</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/c-interop">Bind to native code</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/platform-views">Host a native iOS view</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/ios-debugging">Enable debugging on iOS</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/restore-state-ios">Restore state on iOS</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-22-7" href="/platform-integration/linux" role="button" aria-expanded="false" aria-controls="fixed-sidenav-22-7">Linux</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-22-7"><li class="nav-item"><a class="nav-link" href="/platform-integration/linux/install-linux">Add Linux as build target</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/linux/building">Build a Linux app</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-22-8" href="/platform-integration/macos" role="button" aria-expanded="false" aria-controls="fixed-sidenav-22-8">macOS</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-22-8"><li class="nav-item"><a class="nav-link" href="/platform-integration/macos/install-macos">Add macOS as build target</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/macos/building">Build a macOS app</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/macos/c-interop">Bind to native code</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/macos/platform-views">Host a native macOS view</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-22-9" href="/platform-integration/web" role="button" aria-expanded="false" aria-controls="fixed-sidenav-22-9">Web</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-22-9"><li class="nav-item"><a class="nav-link" href="/platform-integration/web">Web support in Flutter</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/install-web">Add web as build target</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/building">Build a web app</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/wasm">Compile to WebAssembly</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/initialization">Customize app initialization</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/embedding-flutter-web">Add Flutter to any web app</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/web-content-in-flutter">Web content in Flutter</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/renderers">Web renderers</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/web-images">Display images on the web</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/faq">Web FAQ</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-22-10" href="/platform-integration/windows" role="button" aria-expanded="false" aria-controls="fixed-sidenav-22-10">Windows</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-22-10"><li class="nav-item"><a class="nav-link" href="/platform-integration/windows/install-windows">Add Windows as build target</a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/windows/building">Build a Windows app</a></li></ul></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#fixed-sidenav-23" role="button" aria-expanded="false" aria-controls="fixed-sidenav-23">Packages & plugins</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-23"><li class="nav-item"><a class="nav-link" href="/packages-and-plugins/using-packages">Use packages & plugins</a></li><li class="nav-item"><a class="nav-link" href="/packages-and-plugins/developing-packages">Develop packages & plugins</a></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-23-3" href="/packages-and-plugins/swift-package-manager" role="button" aria-expanded="false" aria-controls="fixed-sidenav-23-3">Swift Package Manager</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-23-3"><li class="nav-item"><a class="nav-link" href="/packages-and-plugins/swift-package-manager/for-app-developers">For app developers</a></li><li class="nav-item"><a class="nav-link" href="/packages-and-plugins/swift-package-manager/for-plugin-authors">For plugin authors</a></li></ul></li><div class="dropdown-divider"></div><li class="nav-item"><a class="nav-link" href="/packages-and-plugins/favorites">Flutter Favorites</a></li><li class="nav-item"><a class="nav-link" href="https://pub.dev/flutter" target="_blank" rel="noopener">Package repository</a></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#fixed-sidenav-24" role="button" aria-expanded="false" aria-controls="fixed-sidenav-24">Testing & debugging</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-24"><li class="nav-header">Testing</li><li class="nav-item"><a class="nav-link" href="/testing/overview">Overview</a></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-24-3" href="#fixed-sidenav-24-3" role="button" aria-expanded="false" aria-controls="fixed-sidenav-24-3">Unit testing</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-24-3"><li class="nav-item"><a class="nav-link" href="/cookbook/testing/unit/introduction">Introduction</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/testing/unit/mocking">Mock dependencies</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-24-4" href="#fixed-sidenav-24-4" role="button" aria-expanded="false" aria-controls="fixed-sidenav-24-4">Widget testing</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-24-4"><li class="nav-item"><a class="nav-link" href="/cookbook/testing/widget/introduction">Introduction</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/testing/widget/finders">Find widgets</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/testing/widget/scrolling">Simulate scrolling</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/testing/widget/tap-drag">Simulate user interaction</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-24-5" href="#fixed-sidenav-24-5" role="button" aria-expanded="false" aria-controls="fixed-sidenav-24-5">Integration testing</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-24-5"><li class="nav-item"><a class="nav-link" href="/cookbook/testing/integration/introduction">Introduction</a></li><li class="nav-item"><a class="nav-link" href="/testing/integration-tests">Write and run an integration test</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/testing/integration/profiling">Profile an integration test</a></li></ul></li><li class="nav-item"><a class="nav-link" href="/testing/testing-plugins">Test a plugin</a></li><li class="nav-item"><a class="nav-link" href="/testing/plugins-in-tests">Handle plugin code in tests</a></li><li class="nav-header">Debugging</li><li class="nav-item"><a class="nav-link" href="/testing/debugging">Debugging tools</a></li><li class="nav-item"><a class="nav-link" href="/testing/code-debugging">Debug your app programmatically</a></li><li class="nav-item"><a class="nav-link" href="/testing/native-debugging">Use a native language debugger</a></li><li class="nav-item"><a class="nav-link" href="/testing/build-modes">Flutter's build modes</a></li><li class="nav-item"><a class="nav-link" href="/testing/common-errors">Common Flutter errors</a></li><li class="nav-item"><a class="nav-link" href="/testing/errors">Handle errors</a></li><li class="nav-item"><a class="nav-link" href="/cookbook/maintenance/error-reporting">Report errors to a service</a></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#fixed-sidenav-25" role="button" aria-expanded="false" aria-controls="fixed-sidenav-25">Performance & optimization</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-25"><li class="nav-item"><a class="nav-link" href="/perf">Overview</a></li><li class="nav-item"><a class="nav-link" href="/perf/impeller">Impeller</a></li><li class="nav-item"><a class="nav-link" href="/perf/best-practices">Performance best practices</a></li><li class="nav-item"><a class="nav-link" href="/perf/app-size">App size</a></li><li class="nav-item"><a class="nav-link" href="/perf/deferred-components">Deferred components</a></li><li class="nav-item"><a class="nav-link" href="/perf/rendering-performance">Rendering performance</a></li><li class="nav-item"><a class="nav-link" href="/perf/ui-performance">Performance profiling</a></li><li class="nav-item"><a class="nav-link" href="/perf/web-performance">Performance profiling for web</a></li><li class="nav-item"><a class="nav-link" href="/perf/shader">Shader compilation jank</a></li><li class="nav-item"><a class="nav-link" href="/perf/metrics">Performance metrics</a></li><li class="nav-item"><a class="nav-link" href="/perf/isolates">Concurrency and isolates</a></li><li class="nav-item"><a class="nav-link" href="/perf/faq">Performance FAQ</a></li><li class="nav-item"><a class="nav-link" href="/perf/appendix">Appendix</a></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#fixed-sidenav-26" role="button" aria-expanded="false" aria-controls="fixed-sidenav-26">Deployment</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-26"><li class="nav-item"><a class="nav-link" href="/deployment/obfuscate">Obfuscate Dart code</a></li><li class="nav-item"><a class="nav-link" href="/deployment/flavors">Create flavors of an app</a></li><li class="nav-item"><a class="nav-link" href="/deployment/android">Build and release an Android app</a></li><li class="nav-item"><a class="nav-link" href="/deployment/ios">Build and release an iOS app</a></li><li class="nav-item"><a class="nav-link" href="/deployment/macos">Build and release a macOS app</a></li><li class="nav-item"><a class="nav-link" href="/deployment/linux">Build and release a Linux app</a></li><li class="nav-item"><a class="nav-link" href="/deployment/windows">Build and release a Windows app</a></li><li class="nav-item"><a class="nav-link" href="/deployment/web">Build and release a web app</a></li><li class="nav-item"><a class="nav-link" href="/deployment/cd">Set up continuous deployment</a></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#fixed-sidenav-27" role="button" aria-expanded="false" aria-controls="fixed-sidenav-27">Add to an existing app</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-27"><li class="nav-item"><a class="nav-link" href="/add-to-app">Introduction</a></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-27-2" href="/add-to-app/android" role="button" aria-expanded="false" aria-controls="fixed-sidenav-27-2">Add to an Android app</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-27-2"><li class="nav-item"><a class="nav-link" href="/add-to-app/android/project-setup">Set up Android project</a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/android/add-flutter-screen">Add a single Flutter screen</a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/android/add-flutter-fragment">Add a Flutter Fragment</a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/android/add-flutter-view">Add a Flutter View</a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/android/plugin-setup">Use a Flutter plugin</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-27-3" href="/add-to-app/ios" role="button" aria-expanded="false" aria-controls="fixed-sidenav-27-3">Add to an iOS app</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-27-3"><li class="nav-item"><a class="nav-link" href="/add-to-app/ios/project-setup">Set up iOS project</a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/ios/add-flutter-screen">Add a single Flutter screen</a></li></ul></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/embedding-flutter-web">Add to a web app</a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/debugging">Debug embedded Flutter module</a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/multiple-flutters">Add multiple Flutter instances</a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/performance">Loading sequence and performance</a></li></ul></li><li aria-hidden="true"><div class="sidebar-primary-divider"></div></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#fixed-sidenav-29" role="button" aria-expanded="false" aria-controls="fixed-sidenav-29">Tools & editors</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-29"><li class="nav-item"><a class="nav-link" href="/tools/android-studio">Android Studio & IntelliJ</a></li><li class="nav-item"><a class="nav-link" href="/tools/vs-code">Visual Studio Code</a></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-29-3" href="/tools/devtools" role="button" aria-expanded="false" aria-controls="fixed-sidenav-29-3">DevTools</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-29-3"><li class="nav-item"><a class="nav-link" href="/tools/devtools">Overview</a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/android-studio">Run from Android Studio & IntelliJ</a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/vscode">Run from VS Code</a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/cli">Run from command line</a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/inspector">Flutter inspector</a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/performance">Performance view</a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/cpu-profiler">CPU Profiler view</a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/memory">Memory view</a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/console">Debug console view</a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/network">Network view</a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/debugger">Debugger</a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/logging">Logging view</a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/app-size">App size tool</a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/extensions">DevTools extensions</a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/deep-links">Validate deep links</a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/release-notes">Release notes</a></li></ul></li><li class="nav-item"><a class="nav-link" href="/tools/sdk">SDK overview</a></li><li class="nav-item"><a class="nav-link" href="/tools/pubspec">Flutter's pubspec options</a></li><li class="nav-item"><a class="nav-link" href="/tools/flutter-fix">Automated fixes</a></li><li class="nav-item"><a class="nav-link" href="/tools/formatting">Code formatting</a></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#fixed-sidenav-30" role="button" aria-expanded="false" aria-controls="fixed-sidenav-30">Flutter concepts</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-30"><li class="nav-item"><a class="nav-link" href="/resources/architectural-overview">Architectural overview</a></li><li class="nav-item"><a class="nav-link" href="/resources/inside-flutter">Inside Flutter</a></li><li class="nav-item"><a class="nav-link" href="/ui/layout/constraints">Understanding constraints</a></li><li class="nav-item"><a class="nav-link" href="/testing/build-modes">Flutter's build modes</a></li><li class="nav-item"><a class="nav-link" href="/tools/hot-reload">Hot reload</a></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#fixed-sidenav-31" role="button" aria-expanded="false" aria-controls="fixed-sidenav-31">Resources</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-31"><li class="nav-item"><a class="nav-link" href="/resources/faq">FAQ</a></li><li class="nav-item"><a class="nav-link" href="/resources/books">Books</a></li><li class="nav-item"><a class="nav-link" href="/resources/videos">Videos</a></li><li class="nav-item"><a class="nav-link" href="/resources/courses">Courses</a></li><li class="nav-item"><a class="nav-link" href="/resources/bootstrap-into-dart">Learn Dart</a></li><li class="nav-item"><a class="nav-link" href="/resources/support">Get support</a></li><div class="dropdown-divider"></div><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-31-8" href="#fixed-sidenav-31-8" role="button" aria-expanded="false" aria-controls="fixed-sidenav-31-8">Contribute</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-31-8"><li class="nav-item"><a class="nav-link" href="/resources/bug-reports">Create useful bug reports</a></li><li class="nav-item"><a class="nav-link" href="https://github.com/flutter/flutter/blob/main/CONTRIBUTING.md" target="_blank" rel="noopener">Contribute to Flutter</a></li><li class="nav-item"><a class="nav-link" href="/resources/design-docs">Discover proposed features</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#fixed-sidenav-31-9" href="/reference" role="button" aria-expanded="false" aria-controls="fixed-sidenav-31-9">Reference</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-31-9"><li class="nav-item"><a class="nav-link" href="/dash">Who is Dash?</a></li><li class="nav-item"><a class="nav-link" href="/reference/widgets">Widget index</a></li><li class="nav-item"><a class="nav-link" href="/reference/flutter-cli">flutter CLI</a></li><li class="nav-item"><a class="nav-link" href="https://api.flutter.dev" target="_blank" rel="noopener">API docs</a></li></ul></li></ul></li></ul></div><main class="site-content col-12 col-md-9 offset-md-3 col-xl-8 offset-xl-2 col-xxl-8 offset-xxl-2"><div id="site-toc--side" class="site-toc fixed-col col-xl-2 order-3" data-fixed-column><header class="site-toc__title">Contents</header><ul class="section-nav"><li class="toc-entry nav-item toc-h2"><a class="nav-link" href="#stateful-and-stateless-widgets">Stateful and stateless widgets</a></li><li class="toc-entry nav-item toc-h2"><a class="nav-link" href="#creating-a-stateful-widget">Creating a stateful widget</a><ul class="nav"><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#step-0-get-ready">Step 0: Get ready</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#step-1-decide-which-object-manages-the-widgets-state">Step 1: Decide which object manages the widget's state</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#step-2-subclass-statefulwidget">Step 2: Subclass StatefulWidget</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#step-3-subclass-state">Step 3: Subclass State</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#step-4-plug-the-stateful-widget-into-the-widget-tree">Step 4: Plug the stateful widget into the widget tree</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#problems">Problems?</a></li></ul></li><li class="toc-entry nav-item toc-h2"><a class="nav-link" href="#managing-state">Managing state</a><ul class="nav"><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#the-widget-manages-its-own-state">The widget manages its own state</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#the-parent-widget-manages-the-widgets-state">The parent widget manages the widget's state</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#a-mix-and-match-approach">A mix-and-match approach</a></li></ul></li><li class="toc-entry nav-item toc-h2"><a class="nav-link" href="#other-interactive-widgets">Other interactive widgets</a><ul class="nav"><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#standard-widgets">Standard widgets</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#material-components">Material Components</a></li></ul></li><li class="toc-entry nav-item toc-h2"><a class="nav-link" href="#resources">Resources</a></li></ul></div><div class="container"><header class="site-content__title" id="site-content-title"><h1>Add interactivity to your Flutter app</h1><nav class="breadcrumbs" aria-label="breadcrumb"><ol class="breadcrumb-list" vocab="https://schema.org/" typeof="BreadcrumbList"><li class="breadcrumb-item" property="itemListElement" typeof="ListItem"><a href="/ui" property="item" typeof="WebPage"><span property="name">UI</span></a><meta property="position" content="0"><span class="material-symbols-outlined child-icon" aria-hidden="true">chevron_right</span></li><li class="breadcrumb-item active" property="itemListElement" typeof="ListItem" aria-current="page"><a href="/ui/interactivity" property="item" typeof="WebPage"><span property="name">Interactivity</span></a><meta property="position" content="1"></li></ol></nav></header><div id="site-toc--inline" class="site-toc toc-collapsible toc-collapsed"><header class="site-toc__title">Contents <span class="site-toc--inline__toggle toc-toggle-down" title="Expand table of contents"><i class="material-symbols" aria-hidden="true">keyboard_arrow_down</i></span> <span class="site-toc--inline__toggle toc-toggle-up" title="Collapse table of contents"><i class="material-symbols" aria-hidden="true">keyboard_arrow_up</i></span></header><ul class="section-nav"><li class="toc-entry toc-h2"><a href="#stateful-and-stateless-widgets">Stateful and stateless widgets</a></li><li class="toc-entry toc-h2"><a href="#creating-a-stateful-widget">Creating a stateful widget</a><ul><li class="toc-entry toc-h3"><a href="#step-0-get-ready">Step 0: Get ready</a></li><li class="toc-entry toc-h3"><a href="#step-1-decide-which-object-manages-the-widgets-state">Step 1: Decide which object manages the widget's state</a></li><li class="toc-entry toc-h3"><a href="#step-2-subclass-statefulwidget">Step 2: Subclass StatefulWidget</a></li><li class="toc-entry toc-h3"><a href="#step-3-subclass-state">Step 3: Subclass State</a></li><li class="toc-entry toc-h3"><a href="#step-4-plug-the-stateful-widget-into-the-widget-tree">Step 4: Plug the stateful widget into the widget tree</a></li><li class="toc-entry toc-h3"><a href="#problems">Problems?</a></li></ul></li><li class="toc-entry toc-h2"><a href="#managing-state">Managing state</a><ul><li class="toc-entry toc-h3"><a href="#the-widget-manages-its-own-state">The widget manages its own state</a></li><li class="toc-entry toc-h3"><a href="#the-parent-widget-manages-the-widgets-state">The parent widget manages the widget's state</a></li><li class="toc-entry toc-h3"><a href="#a-mix-and-match-approach">A mix-and-match approach</a></li></ul></li><li class="toc-entry toc-h2"><a href="#other-interactive-widgets">Other interactive widgets</a><ul><li class="toc-entry toc-h3"><a href="#standard-widgets">Standard widgets</a></li><li class="toc-entry toc-h3"><a href="#material-components">Material Components</a></li></ul></li><li class="toc-entry toc-h2"><a href="#resources">Resources</a></li></ul><span class="site-toc--inline__toggle toc-toggle-more-items" title="Expand table of contents"><i class="material-symbols" aria-hidden="true">more_horiz</i></span></div><aside class="alert alert-secondary"><div class="alert-header"><span>What you'll learn</span></div><div class="alert-content"><ul><li>How to respond to taps.</li><li>How to create a custom widget.</li><li>The difference between stateless and stateful widgets.</li></ul></div></aside><p>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.</p><p>The <a href="/ui/layout/tutorial">building layouts tutorial</a> showed you how to create the layout for the following screenshot.</p><figure class="site-figure"><div class="site-figure-container"><img src="/assets/images/docs/ui/layout/lakes.jpg" class="site-mobile-screenshot border" alt="The layout tutorial app" style=""><figcaption class="figure-caption">The layout tutorial app</figcaption></div></figure><p>When the app first launches, the star is solid red, indicating that this lake has previously been favorited. The number next to the star indicates that 41 people have favorited this lake. After completing this tutorial, tapping the star removes its favorited status, replacing the solid star with an outline and decreasing the count. Tapping again favorites the lake, drawing a solid star and increasing the count.</p><img src="/assets/images/docs/ui/favorited-not-favorited.png" class="mw-100 text-center" alt="The custom widget you'll create" width="200px"><p>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.</p><p>You can get right to touching the code in <a href="#step-2">Step 2: Subclass StatefulWidget</a>. If you want to try different ways of managing state, skip to <a href="#managing-state">Managing state</a>.</p><div class="header-wrapper"><h2 id="stateful-and-stateless-widgets">Stateful and stateless widgets</h2><a class="heading-link" href="#stateful-and-stateless-widgets" aria-label="Link to 'Stateful and stateless widgets' section">#</a></div><p>A widget is either stateful or stateless. If a widget can change—when a user interacts with it, for example—it's stateful.</p><p>A <em>stateless</em> widget never changes. <a href="https://api.flutter.dev/flutter/widgets/Icon-class.html"><code>Icon</code></a>, <a href="https://api.flutter.dev/flutter/material/IconButton-class.html"><code>IconButton</code></a>, and <a href="https://api.flutter.dev/flutter/widgets/Text-class.html"><code>Text</code></a> are examples of stateless widgets. Stateless widgets subclass <a href="https://api.flutter.dev/flutter/widgets/StatelessWidget-class.html"><code>StatelessWidget</code></a>.</p><p>A <em>stateful</em> widget is dynamic: for example, it can change its appearance in response to events triggered by user interactions or when it receives data. <a href="https://api.flutter.dev/flutter/material/Checkbox-class.html"><code>Checkbox</code></a>, <a href="https://api.flutter.dev/flutter/material/Radio-class.html"><code>Radio</code></a>, <a href="https://api.flutter.dev/flutter/material/Slider-class.html"><code>Slider</code></a>, <a href="https://api.flutter.dev/flutter/material/InkWell-class.html"><code>InkWell</code></a>, <a href="https://api.flutter.dev/flutter/widgets/Form-class.html"><code>Form</code></a>, and <a href="https://api.flutter.dev/flutter/material/TextField-class.html"><code>TextField</code></a> are examples of stateful widgets. Stateful widgets subclass <a href="https://api.flutter.dev/flutter/widgets/StatefulWidget-class.html"><code>StatefulWidget</code></a>.</p><p>A widget's state is stored in a <a href="https://api.flutter.dev/flutter/widgets/State-class.html"><code>State</code></a> 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 <code>setState()</code>, telling the framework to redraw the widget.</p><div class="header-wrapper"><h2 id="creating-a-stateful-widget">Creating a stateful widget</h2><a class="heading-link" href="#creating-a-stateful-widget" aria-label="Link to 'Creating a stateful widget' section">#</a></div><aside class="alert alert-secondary"><div class="alert-header"><span>What's the point?</span></div><div class="alert-content"><ul><li>A stateful widget is implemented by two classes: a subclass of <code>StatefulWidget</code> and a subclass of <code>State</code>.</li><li>The state class contains the widget's mutable state and the widget's <code>build()</code> method.</li><li>When the widget's state changes, the state object calls <code>setState()</code>, telling the framework to redraw the widget.</li></ul></div></aside><p>In this section, you'll create a custom stateful widget. You'll replace two stateless widgets—the solid red star and the numeric count next to it—with a single custom stateful widget that manages a row with two children widgets: an <code>IconButton</code> and <code>Text</code>.</p><p>Implementing a custom stateful widget requires creating two classes:</p><ul><li>A subclass of <code>StatefulWidget</code> that defines the widget.</li><li>A subclass of <code>State</code> that contains the state for that widget and defines the widget's <code>build()</code> method.</li></ul><p>This section shows you how to build a stateful widget, called <code>FavoriteWidget</code>, for the lakes app. After setting up, your first step is choosing how state is managed for <code>FavoriteWidget</code>.</p><div class="header-wrapper"><h3 id="step-0-get-ready">Step 0: Get ready</h3><a class="heading-link" href="#step-0-get-ready" aria-label="Link to 'Step 0: Get ready' section">#</a></div><p>If you've already built the app in the <a href="/ui/layout/tutorial">building layouts tutorial</a>, skip to the next section.</p><ol><li>Make sure you've <a href="/get-started/install">set up</a> your environment.</li><li><a href="/get-started/test-drive">Create a new Flutter app</a>.</li><li>Replace the <code>lib/main.dart</code> file with <a href="https://github.com/flutter/website/tree/main/examples/layout/lakes/step6/lib/main.dart"><code>main.dart</code></a>.</li><li>Replace the <code>pubspec.yaml</code> file with <a href="https://github.com/flutter/website/tree/main/examples/layout/lakes/step6/pubspec.yaml"><code>pubspec.yaml</code></a>.</li><li>Create an <code>images</code> directory in your project, and add <a href="https://github.com/flutter/website/tree/main/examples/layout/lakes/step6/images/lake.jpg"><code>lake.jpg</code></a>.</li></ol><p>Once you have a connected and enabled device, or you've launched the <a href="/get-started/install/macos/mobile-ios#configure-your-target-ios-device">iOS simulator</a> (part of the Flutter install) or the <a href="/get-started/install/windows/mobile?tab=virtual#configure-your-target-android-device">Android emulator</a> (part of the Android Studio install), you are good to go!</p><p><a id="step-1"></a></p><div class="header-wrapper"><h3 id="step-1-decide-which-object-manages-the-widgets-state">Step 1: Decide which object manages the widget's state</h3><a class="heading-link" href="#step-1-decide-which-object-manages-the-widgets-state" aria-label="Link to 'Step 1: Decide which object manages the widget's state' section">#</a></div><p>A widget's state can be managed in several ways, but in our example the widget itself, <code>FavoriteWidget</code>, will manage its own state. In this example, toggling the star is an isolated action that doesn't affect the parent widget or the rest of the UI, so the widget can handle its state internally.</p><p>Learn more about the separation of widget and state, and how state might be managed, in <a href="#managing-state">Managing state</a>.</p><p><a id="step-2"></a></p><div class="header-wrapper"><h3 id="step-2-subclass-statefulwidget">Step 2: Subclass StatefulWidget</h3><a class="heading-link" href="#step-2-subclass-statefulwidget" aria-label="Link to 'Step 2: Subclass StatefulWidget' section">#</a></div><p>The <code>FavoriteWidget</code> class manages its own state, so it overrides <code>createState()</code> to create a <code>State</code> object. The framework calls <code>createState()</code> when it wants to build the widget. In this example, <code>createState()</code> returns an instance of <code>_FavoriteWidgetState</code>, which you'll implement in the next step.</p> <?code-excerpt path-base="layout/lakes/interactive"?> <?code-excerpt "lib/main.dart (favorite-widget)"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#BD2314">class</span><span style="color:#0468D7"> FavoriteWidget</span><span style="color:#BD2314"> extends</span><span style="color:#0468D7"> StatefulWidget</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#BD2314"> const</span><span style="color:#0468D7"> FavoriteWidget</span><span style="color:#222222">({</span><span style="color:#BD2314">super</span><span style="color:#222222">.key});</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> @override</span></span> <span class="line"><span style="color:#0468D7"> State</span><span style="color:#222222"><</span><span style="color:#0468D7">FavoriteWidget</span><span style="color:#222222">> </span><span style="color:#6200EE">createState</span><span style="color:#222222">() => </span><span style="color:#0468D7">_FavoriteWidgetState</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><aside class="alert alert-info"><div class="alert-header"><i class="material-symbols" aria-hidden="true">info</i> <span>Note</span></div><div class="alert-content"><p>Members or classes that start with an underscore (<code>_</code>) are private. For more information, see <a href="https://dart.dev/language/libraries">Libraries and imports</a>, a section in the <a href="https://dart.dev/language">Dart language documentation</a>.</p></div></aside><p><a id="step-3"></a></p><div class="header-wrapper"><h3 id="step-3-subclass-state">Step 3: Subclass State</h3><a class="heading-link" href="#step-3-subclass-state" aria-label="Link to 'Step 3: Subclass State' section">#</a></div><p>The <code>_FavoriteWidgetState</code> class stores the mutable data that can change over the lifetime of the widget. When the app first launches, the UI displays a solid red star, indicating that the lake has "favorite" status, along with 41 likes. These values are stored in the <code>_isFavorited</code> and <code>_favoriteCount</code> fields:</p> <?code-excerpt "lib/main.dart (favorite-state-fields)" replace="/(bool|int) .*/[!$&!]/g"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#BD2314">class</span><span style="color:#0468D7"> _FavoriteWidgetState</span><span style="color:#BD2314"> extends</span><span style="color:#0468D7"> State</span><span style="color:#222222"><</span><span style="color:#0468D7">FavoriteWidget</span><span style="color:#222222">> {</span></span> <span class="line"><span style="color:#0468D7"> </span><mark class="highlight"><span style="color:#0468D7">bool</span><span style="color:#222222"> _isFavorited = </span><span style="color:#0C7064">true</span><span style="color:#222222">;</span></mark></span> <span class="line"><span style="color:#0468D7"> </span><mark class="highlight"><span style="color:#0468D7">int</span><span style="color:#222222"> _favoriteCount = </span><span style="color:#0C7064">41</span><span style="color:#222222">;</span></mark></span></code></pre></div></div><p>The class also defines a <code>build()</code> method, which creates a row containing a red <code>IconButton</code>, and <code>Text</code>. You use <a href="https://api.flutter.dev/flutter/material/IconButton-class.html"><code>IconButton</code></a> (instead of <code>Icon</code>) because it has an <code>onPressed</code> property that defines the callback function (<code>_toggleFavorite</code>) for handling a tap. You'll define the callback function next.</p> <?code-excerpt "lib/main.dart (favorite-state-build)" replace="/build|icon.*|onPressed.*|child: Text.*/[!$&!]/g"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#BD2314">class</span><span style="color:#0468D7"> _FavoriteWidgetState</span><span style="color:#BD2314"> extends</span><span style="color:#0468D7"> State</span><span style="color:#222222"><</span><span style="color:#0468D7">FavoriteWidget</span><span style="color:#222222">> {</span></span> <span class="line"><span style="color:#6E6E70"> // ···</span></span> <span class="line"><span style="color:#BD2314"> @override</span></span> <span class="line"><span style="color:#0468D7"> Widget</span><span style="color:#6200EE"> </span><mark class="highlight"><span style="color:#6200EE">build</span></mark><span style="color:#222222">(</span><span style="color:#0468D7">BuildContext</span><span style="color:#222222"> context) {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#0468D7"> Row</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> mainAxisSize: </span><span style="color:#0468D7">MainAxisSize</span><span style="color:#222222">.min,</span></span> <span class="line"><span style="color:#222222"> children: [</span></span> <span class="line"><span style="color:#0468D7"> Container</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> padding: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> EdgeInsets</span><span style="color:#222222">.</span><span style="color:#6200EE">all</span><span style="color:#222222">(</span><span style="color:#0C7064">0</span><span style="color:#222222">),</span></span> <span class="line"><span style="color:#222222"> child: </span><span style="color:#0468D7">IconButton</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> padding: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> EdgeInsets</span><span style="color:#222222">.</span><span style="color:#6200EE">all</span><span style="color:#222222">(</span><span style="color:#0C7064">0</span><span style="color:#222222">),</span></span> <span class="line"><span style="color:#222222"> alignment: </span><span style="color:#0468D7">Alignment</span><span style="color:#222222">.center,</span></span> <span class="line"><span style="color:#222222"> </span><mark class="highlight"><span style="color:#222222">icon: (_isFavorited</span></mark></span> <span class="line"><span style="color:#222222"> ? </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> Icon</span><span style="color:#222222">(</span><span style="color:#0468D7">Icons</span><span style="color:#222222">.star)</span></span> <span class="line"><span style="color:#222222"> : </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> Icon</span><span style="color:#222222">(</span><span style="color:#0468D7">Icons</span><span style="color:#222222">.star_border)),</span></span> <span class="line"><span style="color:#222222"> color: </span><span style="color:#0468D7">Colors</span><span style="color:#222222">.red[</span><span style="color:#0C7064">500</span><span style="color:#222222">],</span></span> <span class="line"><span style="color:#222222"> </span><mark class="highlight"><span style="color:#222222">onPressed: _toggleFavorite,</span></mark></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#0468D7"> SizedBox</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> width: </span><span style="color:#0C7064">18</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> child: </span><span style="color:#0468D7">SizedBox</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> </span><mark class="highlight"><span style="color:#222222">child: </span><span style="color:#0468D7">Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'</span><span style="color:#0C7064">$</span><span style="color:#222222">_favoriteCount</span><span style="color:#0C7064">'</span><span style="color:#222222">),</span></mark></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#222222"> ],</span></span> <span class="line"><span style="color:#222222"> );</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#6E6E70"> // ···</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><aside class="alert alert-success"><div class="alert-header"><i class="material-symbols" aria-hidden="true">lightbulb</i> <span>Tip</span></div><div class="alert-content"><p>Placing the <code>Text</code> in a <a href="https://api.flutter.dev/flutter/widgets/SizedBox-class.html"><code>SizedBox</code></a> and setting its width prevents a discernible "jump" when the text changes between the values of 40 and 41 — a jump would otherwise occur because those values have different widths.</p></div></aside><p>The <code>_toggleFavorite()</code> method, which is called when the <code>IconButton</code> is pressed, calls <code>setState()</code>. Calling <code>setState()</code> 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 <code>setState()</code> toggles the UI between these two states:</p><ul><li>A <code>star</code> icon and the number 41</li><li>A <code>star_border</code> icon and the number 40</li></ul> <?code-excerpt "lib/main.dart (toggle-favorite)"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#BD2314">void</span><span style="color:#6200EE"> _toggleFavorite</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#6200EE"> setState</span><span style="color:#222222">(() {</span></span> <span class="line"><span style="color:#BD2314"> if</span><span style="color:#222222"> (_isFavorited) {</span></span> <span class="line"><span style="color:#222222"> _favoriteCount -= </span><span style="color:#0C7064">1</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#222222"> _isFavorited = </span><span style="color:#0C7064">false</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#222222"> } </span><span style="color:#BD2314">else</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#222222"> _favoriteCount += </span><span style="color:#0C7064">1</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#222222"> _isFavorited = </span><span style="color:#0C7064">true</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#222222"> });</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><p><a id="step-4"></a></p><div class="header-wrapper"><h3 id="step-4-plug-the-stateful-widget-into-the-widget-tree">Step 4: Plug the stateful widget into the widget tree</h3><a class="heading-link" href="#step-4-plug-the-stateful-widget-into-the-widget-tree" aria-label="Link to 'Step 4: Plug the stateful widget into the widget tree' section">#</a></div><p>Add your custom stateful widget to the widget tree in the app's <code>build()</code> method. First, locate the code that creates the <code>Icon</code> and <code>Text</code>, and delete it. In the same location, create the stateful widget:</p> <?code-excerpt path-base=""?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#222222">child: </span><span style="color:#0468D7">Row</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> children: [</span></span> <span class="line"><span style="color:#6E6E70"> // ...</span></span> <span class="line removed-line"><span style="color:#0468D7"> Icon</span><span style="color:#222222">(</span></span> <span class="line removed-line"><span style="color:#0468D7"> Icons</span><span style="color:#222222">.star,</span></span> <span class="line removed-line"><span style="color:#222222"> color: </span><span style="color:#0468D7">Colors</span><span style="color:#222222">.red[</span><span style="color:#0C7064">500</span><span style="color:#222222">],</span></span> <span class="line removed-line"><span style="color:#222222"> ),</span></span> <span class="line removed-line"><span style="color:#BD2314"> const</span><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'41'</span><span style="color:#222222">),</span></span> <span class="line added-line"><span style="color:#BD2314"> const</span><span style="color:#0468D7"> FavoriteWidget</span><span style="color:#222222">(),</span></span> <span class="line"><span style="color:#222222"> ],</span></span> <span class="line"><span style="color:#222222">),</span></span></code></pre></div></div><p>That's it! When you hot reload the app, the star icon should now respond to taps.</p><div class="header-wrapper"><h3 id="problems">Problems?</h3><a class="heading-link" href="#problems" aria-label="Link to 'Problems?' section">#</a></div><p>If you can't get your code to run, look in your IDE for possible errors. <a href="/testing/debugging">Debugging Flutter apps</a> might help. If you still can't find the problem, check your code against the interactive lakes example on GitHub.</p><ul><li><a href="https://github.com/flutter/website/tree/main/examples/layout/lakes/interactive/lib/main.dart"><code>lib/main.dart</code></a></li><li><a href="https://github.com/flutter/website/tree/main/examples/layout/lakes/interactive/pubspec.yaml"><code>pubspec.yaml</code></a></li><li><a href="https://github.com/flutter/website/tree/main/examples/layout/lakes/interactive/images/lake.jpg"><code>lakes.jpg</code></a></li></ul><p>If you still have questions, refer to any one of the developer <a href="https://flutter.dev/community">community</a> channels.</p><hr><p>The rest of this page covers several ways a widget's state can be managed, and lists other available interactive widgets.</p><div class="header-wrapper"><h2 id="managing-state">Managing state</h2><a class="heading-link" href="#managing-state" aria-label="Link to 'Managing state' section">#</a></div><aside class="alert alert-secondary"><div class="alert-header"><span>What's the point?</span></div><div class="alert-content"><ul><li>There are different approaches for managing state.</li><li>You, as the widget designer, choose which approach to use.</li><li>If in doubt, start by managing state in the parent widget.</li></ul></div></aside><p>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:</p><ul><li><a href="#self-managed">The widget manages its own state</a></li><li><a href="#parent-managed">The parent manages the widget's state</a></li><li><a href="#mix-and-match">A mix-and-match approach</a></li></ul><p>How do you decide which approach to use? The following principles should help you decide:</p><ul><li><p>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.</p></li><li><p>If the state in question is aesthetic, for example an animation, then the state is best managed by the widget itself.</p></li></ul><p>If in doubt, start by managing state in the parent widget.</p><p>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 <code>_active</code> boolean determines the color: green for active or grey for inactive.</p><div class="row mb-4"><div class="col-12 text-center"><img src="/assets/images/docs/ui/tapbox-active-state.png" class="border mt-1 mb-1 mw-100" width="150px" alt="Active state"> <img src="/assets/images/docs/ui/tapbox-inactive-state.png" class="border mt-1 mb-1 mw-100" width="150px" alt="Inactive state"></div></div><p>These examples use <a href="https://api.flutter.dev/flutter/widgets/GestureDetector-class.html"><code>GestureDetector</code></a> to capture activity on the <code>Container</code>.</p><p><a id="self-managed"></a></p><div class="header-wrapper"><h3 id="the-widget-manages-its-own-state">The widget manages its own state</h3><a class="heading-link" href="#the-widget-manages-its-own-state" aria-label="Link to 'The widget manages its own state' section">#</a></div><p>Sometimes it makes the most sense for the widget to manage its state internally. For example, <a href="https://api.flutter.dev/flutter/widgets/ListView-class.html"><code>ListView</code></a> automatically scrolls when its content exceeds the render box. Most developers using <code>ListView</code> don't want to manage <code>ListView</code>'s scrolling behavior, so <code>ListView</code> itself manages its scroll offset.</p><p>The <code>_TapboxAState</code> class:</p><ul><li>Manages state for <code>TapboxA</code>.</li><li>Defines the <code>_active</code> boolean which determines the box's current color.</li><li>Defines the <code>_handleTap()</code> function, which updates <code>_active</code> when the box is tapped and calls the <code>setState()</code> function to update the UI.</li><li>Implements all interactive behavior for the widget.</li></ul> <?code-excerpt path-base="ui/interactive/"?> <?code-excerpt "lib/self_managed.dart"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#BD2314">import</span><span style="color:#0C7064"> 'package:flutter/material.dart'</span><span style="color:#222222">;</span></span> <span class="line"></span> <span class="line"><span style="color:#6E6E70">// TapboxA manages its own state.</span></span> <span class="line"></span> <span class="line"><span style="color:#6E6E70">//------------------------- TapboxA ----------------------------------</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314">class</span><span style="color:#0468D7"> TapboxA</span><span style="color:#BD2314"> extends</span><span style="color:#0468D7"> StatefulWidget</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#BD2314"> const</span><span style="color:#0468D7"> TapboxA</span><span style="color:#222222">({</span><span style="color:#BD2314">super</span><span style="color:#222222">.key});</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> @override</span></span> <span class="line"><span style="color:#0468D7"> State</span><span style="color:#222222"><</span><span style="color:#0468D7">TapboxA</span><span style="color:#222222">> </span><span style="color:#6200EE">createState</span><span style="color:#222222">() => </span><span style="color:#0468D7">_TapboxAState</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#222222">}</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314">class</span><span style="color:#0468D7"> _TapboxAState</span><span style="color:#BD2314"> extends</span><span style="color:#0468D7"> State</span><span style="color:#222222"><</span><span style="color:#0468D7">TapboxA</span><span style="color:#222222">> {</span></span> <span class="line"><span style="color:#0468D7"> bool</span><span style="color:#222222"> _active = </span><span style="color:#0C7064">false</span><span style="color:#222222">;</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> void</span><span style="color:#6200EE"> _handleTap</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#6200EE"> setState</span><span style="color:#222222">(() {</span></span> <span class="line"><span style="color:#222222"> _active = !_active;</span></span> <span class="line"><span style="color:#222222"> });</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> @override</span></span> <span class="line"><span style="color:#0468D7"> Widget</span><span style="color:#6200EE"> build</span><span style="color:#222222">(</span><span style="color:#0468D7">BuildContext</span><span style="color:#222222"> context) {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#0468D7"> GestureDetector</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> onTap: _handleTap,</span></span> <span class="line"><span style="color:#222222"> child: </span><span style="color:#0468D7">Container</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> width: </span><span style="color:#0C7064">200</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> height: </span><span style="color:#0C7064">200</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> decoration: </span><span style="color:#0468D7">BoxDecoration</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> color: _active ? </span><span style="color:#0468D7">Colors</span><span style="color:#222222">.lightGreen[</span><span style="color:#0C7064">700</span><span style="color:#222222">] : </span><span style="color:#0468D7">Colors</span><span style="color:#222222">.grey[</span><span style="color:#0C7064">600</span><span style="color:#222222">],</span></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#222222"> child: </span><span style="color:#0468D7">Center</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> child: </span><span style="color:#0468D7">Text</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> _active ? </span><span style="color:#0C7064">'Active'</span><span style="color:#222222"> : </span><span style="color:#0C7064">'Inactive'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> style: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> TextStyle</span><span style="color:#222222">(fontSize: </span><span style="color:#0C7064">32</span><span style="color:#222222">, color: </span><span style="color:#0468D7">Colors</span><span style="color:#222222">.white),</span></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#222222"> );</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#222222">}</span></span> <span class="line"></span> <span class="line"><span style="color:#6E6E70">//------------------------- MyApp ----------------------------------</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314">class</span><span style="color:#0468D7"> MyApp</span><span style="color:#BD2314"> extends</span><span style="color:#0468D7"> StatelessWidget</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#BD2314"> const</span><span style="color:#0468D7"> MyApp</span><span style="color:#222222">({</span><span style="color:#BD2314">super</span><span style="color:#222222">.key});</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> @override</span></span> <span class="line"><span style="color:#0468D7"> Widget</span><span style="color:#6200EE"> build</span><span style="color:#222222">(</span><span style="color:#0468D7">BuildContext</span><span style="color:#222222"> context) {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#0468D7"> MaterialApp</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> title: </span><span style="color:#0C7064">'Flutter Demo'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> home: </span><span style="color:#0468D7">Scaffold</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> appBar: </span><span style="color:#0468D7">AppBar</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> title: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'Flutter Demo'</span><span style="color:#222222">),</span></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#222222"> body: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> Center</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> child: </span><span style="color:#0468D7">TapboxA</span><span style="color:#222222">(),</span></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#222222"> );</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><hr><p><a id="parent-managed"></a></p><div class="header-wrapper"><h3 id="the-parent-widget-manages-the-widgets-state">The parent widget manages the widget's state</h3><a class="heading-link" href="#the-parent-widget-manages-the-widgets-state" aria-label="Link to 'The parent widget manages the widget's state' section">#</a></div><p>Often it makes the most sense for the parent widget to manage the state and tell its child widget when to update. For example, <a href="https://api.flutter.dev/flutter/material/IconButton-class.html"><code>IconButton</code></a> allows you to treat an icon as a tappable button. <code>IconButton</code> is a stateless widget because we decided that the parent widget needs to know whether the button has been tapped, so it can take appropriate action.</p><p>In the following example, TapboxB exports its state to its parent through a callback. Because TapboxB doesn't manage any state, it subclasses StatelessWidget.</p><p>The ParentWidgetState class:</p><ul><li>Manages the <code>_active</code> state for TapboxB.</li><li>Implements <code>_handleTapboxChanged()</code>, the method called when the box is tapped.</li><li>When the state changes, calls <code>setState()</code> to update the UI.</li></ul><p>The TapboxB class:</p><ul><li>Extends StatelessWidget because all state is handled by its parent.</li><li>When a tap is detected, it notifies the parent.</li></ul> <?code-excerpt "lib/parent_managed.dart"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#BD2314">import</span><span style="color:#0C7064"> 'package:flutter/material.dart'</span><span style="color:#222222">;</span></span> <span class="line"></span> <span class="line"><span style="color:#6E6E70">// ParentWidget manages the state for TapboxB.</span></span> <span class="line"></span> <span class="line"><span style="color:#6E6E70">//------------------------ ParentWidget --------------------------------</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314">class</span><span style="color:#0468D7"> ParentWidget</span><span style="color:#BD2314"> extends</span><span style="color:#0468D7"> StatefulWidget</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#BD2314"> const</span><span style="color:#0468D7"> ParentWidget</span><span style="color:#222222">({</span><span style="color:#BD2314">super</span><span style="color:#222222">.key});</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> @override</span></span> <span class="line"><span style="color:#0468D7"> State</span><span style="color:#222222"><</span><span style="color:#0468D7">ParentWidget</span><span style="color:#222222">> </span><span style="color:#6200EE">createState</span><span style="color:#222222">() => </span><span style="color:#0468D7">_ParentWidgetState</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#222222">}</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314">class</span><span style="color:#0468D7"> _ParentWidgetState</span><span style="color:#BD2314"> extends</span><span style="color:#0468D7"> State</span><span style="color:#222222"><</span><span style="color:#0468D7">ParentWidget</span><span style="color:#222222">> {</span></span> <span class="line"><span style="color:#0468D7"> bool</span><span style="color:#222222"> _active = </span><span style="color:#0C7064">false</span><span style="color:#222222">;</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> void</span><span style="color:#6200EE"> _handleTapboxChanged</span><span style="color:#222222">(</span><span style="color:#0468D7">bool</span><span style="color:#222222"> newValue) {</span></span> <span class="line"><span style="color:#6200EE"> setState</span><span style="color:#222222">(() {</span></span> <span class="line"><span style="color:#222222"> _active = newValue;</span></span> <span class="line"><span style="color:#222222"> });</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> @override</span></span> <span class="line"><span style="color:#0468D7"> Widget</span><span style="color:#6200EE"> build</span><span style="color:#222222">(</span><span style="color:#0468D7">BuildContext</span><span style="color:#222222"> context) {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#0468D7"> SizedBox</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> child: </span><span style="color:#0468D7">TapboxB</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> active: _active,</span></span> <span class="line"><span style="color:#222222"> onChanged: _handleTapboxChanged,</span></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#222222"> );</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#222222">}</span></span> <span class="line"></span> <span class="line"><span style="color:#6E6E70">//------------------------- TapboxB ----------------------------------</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314">class</span><span style="color:#0468D7"> TapboxB</span><span style="color:#BD2314"> extends</span><span style="color:#0468D7"> StatelessWidget</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#BD2314"> const</span><span style="color:#0468D7"> TapboxB</span><span style="color:#222222">({</span></span> <span class="line"><span style="color:#BD2314"> super</span><span style="color:#222222">.key,</span></span> <span class="line"><span style="color:#BD2314"> this</span><span style="color:#222222">.active = </span><span style="color:#0C7064">false</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#BD2314"> required</span><span style="color:#BD2314"> this</span><span style="color:#222222">.onChanged,</span></span> <span class="line"><span style="color:#222222"> });</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> bool</span><span style="color:#222222"> active;</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> ValueChanged</span><span style="color:#222222"><</span><span style="color:#0468D7">bool</span><span style="color:#222222">> onChanged;</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> void</span><span style="color:#6200EE"> _handleTap</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#6200EE"> onChanged</span><span style="color:#222222">(!active);</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> @override</span></span> <span class="line"><span style="color:#0468D7"> Widget</span><span style="color:#6200EE"> build</span><span style="color:#222222">(</span><span style="color:#0468D7">BuildContext</span><span style="color:#222222"> context) {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#0468D7"> GestureDetector</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> onTap: _handleTap,</span></span> <span class="line"><span style="color:#222222"> child: </span><span style="color:#0468D7">Container</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> width: </span><span style="color:#0C7064">200</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> height: </span><span style="color:#0C7064">200</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> decoration: </span><span style="color:#0468D7">BoxDecoration</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> color: active ? </span><span style="color:#0468D7">Colors</span><span style="color:#222222">.lightGreen[</span><span style="color:#0C7064">700</span><span style="color:#222222">] : </span><span style="color:#0468D7">Colors</span><span style="color:#222222">.grey[</span><span style="color:#0C7064">600</span><span style="color:#222222">],</span></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#222222"> child: </span><span style="color:#0468D7">Center</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> child: </span><span style="color:#0468D7">Text</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> active ? </span><span style="color:#0C7064">'Active'</span><span style="color:#222222"> : </span><span style="color:#0C7064">'Inactive'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> style: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> TextStyle</span><span style="color:#222222">(fontSize: </span><span style="color:#0C7064">32</span><span style="color:#222222">, color: </span><span style="color:#0468D7">Colors</span><span style="color:#222222">.white),</span></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#222222"> );</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><hr><p><a id="mix-and-match"></a></p><div class="header-wrapper"><h3 id="a-mix-and-match-approach">A mix-and-match approach</h3><a class="heading-link" href="#a-mix-and-match-approach" aria-label="Link to 'A mix-and-match approach' section">#</a></div><p>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.</p><p>In the <code>TapboxC</code> example, on tap down, a dark green border appears around the box. On tap up, the border disappears and the box's color changes. <code>TapboxC</code> exports its <code>_active</code> state to its parent but manages its <code>_highlight</code> state internally. This example has two <code>State</code> objects, <code>_ParentWidgetState</code> and <code>_TapboxCState</code>.</p><p>The <code>_ParentWidgetState</code> object:</p><ul><li>Manages the <code>_active</code> state.</li><li>Implements <code>_handleTapboxChanged()</code>, the method called when the box is tapped.</li><li>Calls <code>setState()</code> to update the UI when a tap occurs and the <code>_active</code> state changes.</li></ul><p>The <code>_TapboxCState</code> object:</p><ul><li>Manages the <code>_highlight</code> state.</li><li>The <code>GestureDetector</code> listens to all tap events. As the user taps down, it adds the highlight (implemented as a dark green border). As the user releases the tap, it removes the highlight.</li><li>Calls <code>setState()</code> to update the UI on tap down, tap up, or tap cancel, and the <code>_highlight</code> state changes.</li><li>On a tap event, passes that state change to the parent widget to take appropriate action using the <a href="https://api.flutter.dev/flutter/widgets/State/widget.html"><code>widget</code></a> property.</li></ul> <?code-excerpt "lib/mixed.dart"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#BD2314">import</span><span style="color:#0C7064"> 'package:flutter/material.dart'</span><span style="color:#222222">;</span></span> <span class="line"></span> <span class="line"><span style="color:#6E6E70">//---------------------------- ParentWidget ----------------------------</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314">class</span><span style="color:#0468D7"> ParentWidget</span><span style="color:#BD2314"> extends</span><span style="color:#0468D7"> StatefulWidget</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#BD2314"> const</span><span style="color:#0468D7"> ParentWidget</span><span style="color:#222222">({</span><span style="color:#BD2314">super</span><span style="color:#222222">.key});</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> @override</span></span> <span class="line"><span style="color:#0468D7"> State</span><span style="color:#222222"><</span><span style="color:#0468D7">ParentWidget</span><span style="color:#222222">> </span><span style="color:#6200EE">createState</span><span style="color:#222222">() => </span><span style="color:#0468D7">_ParentWidgetState</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#222222">}</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314">class</span><span style="color:#0468D7"> _ParentWidgetState</span><span style="color:#BD2314"> extends</span><span style="color:#0468D7"> State</span><span style="color:#222222"><</span><span style="color:#0468D7">ParentWidget</span><span style="color:#222222">> {</span></span> <span class="line"><span style="color:#0468D7"> bool</span><span style="color:#222222"> _active = </span><span style="color:#0C7064">false</span><span style="color:#222222">;</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> void</span><span style="color:#6200EE"> _handleTapboxChanged</span><span style="color:#222222">(</span><span style="color:#0468D7">bool</span><span style="color:#222222"> newValue) {</span></span> <span class="line"><span style="color:#6200EE"> setState</span><span style="color:#222222">(() {</span></span> <span class="line"><span style="color:#222222"> _active = newValue;</span></span> <span class="line"><span style="color:#222222"> });</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> @override</span></span> <span class="line"><span style="color:#0468D7"> Widget</span><span style="color:#6200EE"> build</span><span style="color:#222222">(</span><span style="color:#0468D7">BuildContext</span><span style="color:#222222"> context) {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#0468D7"> SizedBox</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> child: </span><span style="color:#0468D7">TapboxC</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> active: _active,</span></span> <span class="line"><span style="color:#222222"> onChanged: _handleTapboxChanged,</span></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#222222"> );</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#222222">}</span></span> <span class="line"></span> <span class="line"><span style="color:#6E6E70">//----------------------------- TapboxC ------------------------------</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314">class</span><span style="color:#0468D7"> TapboxC</span><span style="color:#BD2314"> extends</span><span style="color:#0468D7"> StatefulWidget</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#BD2314"> const</span><span style="color:#0468D7"> TapboxC</span><span style="color:#222222">({</span></span> <span class="line"><span style="color:#BD2314"> super</span><span style="color:#222222">.key,</span></span> <span class="line"><span style="color:#BD2314"> this</span><span style="color:#222222">.active = </span><span style="color:#0C7064">false</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#BD2314"> required</span><span style="color:#BD2314"> this</span><span style="color:#222222">.onChanged,</span></span> <span class="line"><span style="color:#222222"> });</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> bool</span><span style="color:#222222"> active;</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> ValueChanged</span><span style="color:#222222"><</span><span style="color:#0468D7">bool</span><span style="color:#222222">> onChanged;</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> @override</span></span> <span class="line"><span style="color:#0468D7"> State</span><span style="color:#222222"><</span><span style="color:#0468D7">TapboxC</span><span style="color:#222222">> </span><span style="color:#6200EE">createState</span><span style="color:#222222">() => </span><span style="color:#0468D7">_TapboxCState</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#222222">}</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314">class</span><span style="color:#0468D7"> _TapboxCState</span><span style="color:#BD2314"> extends</span><span style="color:#0468D7"> State</span><span style="color:#222222"><</span><span style="color:#0468D7">TapboxC</span><span style="color:#222222">> {</span></span> <span class="line"><span style="color:#0468D7"> bool</span><span style="color:#222222"> _highlight = </span><span style="color:#0C7064">false</span><span style="color:#222222">;</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> void</span><span style="color:#6200EE"> _handleTapDown</span><span style="color:#222222">(</span><span style="color:#0468D7">TapDownDetails</span><span style="color:#222222"> details) {</span></span> <span class="line"><span style="color:#6200EE"> setState</span><span style="color:#222222">(() {</span></span> <span class="line"><span style="color:#222222"> _highlight = </span><span style="color:#0C7064">true</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#222222"> });</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> void</span><span style="color:#6200EE"> _handleTapUp</span><span style="color:#222222">(</span><span style="color:#0468D7">TapUpDetails</span><span style="color:#222222"> details) {</span></span> <span class="line"><span style="color:#6200EE"> setState</span><span style="color:#222222">(() {</span></span> <span class="line"><span style="color:#222222"> _highlight = </span><span style="color:#0C7064">false</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#222222"> });</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> void</span><span style="color:#6200EE"> _handleTapCancel</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#6200EE"> setState</span><span style="color:#222222">(() {</span></span> <span class="line"><span style="color:#222222"> _highlight = </span><span style="color:#0C7064">false</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#222222"> });</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> void</span><span style="color:#6200EE"> _handleTap</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#222222"> widget.</span><span style="color:#6200EE">onChanged</span><span style="color:#222222">(!widget.active);</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> @override</span></span> <span class="line"><span style="color:#0468D7"> Widget</span><span style="color:#6200EE"> build</span><span style="color:#222222">(</span><span style="color:#0468D7">BuildContext</span><span style="color:#222222"> context) {</span></span> <span class="line"><span style="color:#6E6E70"> // This example adds a green border on tap down.</span></span> <span class="line"><span style="color:#6E6E70"> // On tap up, the square changes to the opposite state.</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#0468D7"> GestureDetector</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> onTapDown: _handleTapDown, </span><span style="color:#6E6E70">// Handle the tap events in the order that</span></span> <span class="line"><span style="color:#222222"> onTapUp: _handleTapUp, </span><span style="color:#6E6E70">// they occur: down, up, tap, cancel</span></span> <span class="line"><span style="color:#222222"> onTap: _handleTap,</span></span> <span class="line"><span style="color:#222222"> onTapCancel: _handleTapCancel,</span></span> <span class="line"><span style="color:#222222"> child: </span><span style="color:#0468D7">Container</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> width: </span><span style="color:#0C7064">200</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> height: </span><span style="color:#0C7064">200</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> decoration: </span><span style="color:#0468D7">BoxDecoration</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> color: widget.active ? </span><span style="color:#0468D7">Colors</span><span style="color:#222222">.lightGreen[</span><span style="color:#0C7064">700</span><span style="color:#222222">] : </span><span style="color:#0468D7">Colors</span><span style="color:#222222">.grey[</span><span style="color:#0C7064">600</span><span style="color:#222222">],</span></span> <span class="line"><span style="color:#222222"> border: _highlight</span></span> <span class="line"><span style="color:#222222"> ? </span><span style="color:#0468D7">Border</span><span style="color:#222222">.</span><span style="color:#6200EE">all</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> color: </span><span style="color:#0468D7">Colors</span><span style="color:#222222">.teal[</span><span style="color:#0C7064">700</span><span style="color:#222222">]!,</span></span> <span class="line"><span style="color:#222222"> width: </span><span style="color:#0C7064">10</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> )</span></span> <span class="line"><span style="color:#222222"> : </span><span style="color:#0C7064">null</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#222222"> child: </span><span style="color:#0468D7">Center</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> child: </span><span style="color:#0468D7">Text</span><span style="color:#222222">(widget.active ? </span><span style="color:#0C7064">'Active'</span><span style="color:#222222"> : </span><span style="color:#0C7064">'Inactive'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> style: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> TextStyle</span><span style="color:#222222">(fontSize: </span><span style="color:#0C7064">32</span><span style="color:#222222">, color: </span><span style="color:#0468D7">Colors</span><span style="color:#222222">.white)),</span></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#222222"> );</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><p>An alternate implementation might have exported the highlight state to the parent while keeping the active state internal, but if you asked someone to use that tap box, they'd probably complain that it doesn't make much sense. The developer cares whether the box is active. The developer probably doesn't care how the highlighting is managed, and prefers that the tap box handles those details.</p><hr><div class="header-wrapper"><h2 id="other-interactive-widgets">Other interactive widgets</h2><a class="heading-link" href="#other-interactive-widgets" aria-label="Link to 'Other interactive widgets' section">#</a></div><p>Flutter offers a variety of buttons and similar interactive widgets. Most of these widgets implement the <a href="https://m3.material.io/styles">Material Design guidelines</a>, which define a set of components with an opinionated UI.</p><p>If you prefer, you can use <a href="https://api.flutter.dev/flutter/widgets/GestureDetector-class.html"><code>GestureDetector</code></a> to build interactivity into any custom widget. You can find examples of <code>GestureDetector</code> in <a href="#managing-state">Managing state</a>. Learn more about the <code>GestureDetector</code> in <a href="/cookbook/gestures/handling-taps">Handle taps</a>, a recipe in the <a href="/cookbook">Flutter cookbook</a>.</p><aside class="alert alert-success"><div class="alert-header"><i class="material-symbols" aria-hidden="true">lightbulb</i> <span>Tip</span></div><div class="alert-content"><p>Flutter also provides a set of iOS-style widgets called <a href="https://api.flutter.dev/flutter/cupertino/cupertino-library.html"><code>Cupertino</code></a>.</p></div></aside><p>When you need interactivity, it's easiest to use one of the prefabricated widgets. Here's a partial list:</p><div class="header-wrapper"><h3 id="standard-widgets">Standard widgets</h3><a class="heading-link" href="#standard-widgets" aria-label="Link to 'Standard widgets' section">#</a></div><ul><li><a href="https://api.flutter.dev/flutter/widgets/Form-class.html"><code>Form</code></a></li><li><a href="https://api.flutter.dev/flutter/widgets/FormField-class.html"><code>FormField</code></a></li></ul><div class="header-wrapper"><h3 id="material-components">Material Components</h3><a class="heading-link" href="#material-components" aria-label="Link to 'Material Components' section">#</a></div><ul><li><a href="https://api.flutter.dev/flutter/material/Checkbox-class.html"><code>Checkbox</code></a></li><li><a href="https://api.flutter.dev/flutter/material/DropdownButton-class.html"><code>DropdownButton</code></a></li><li><a href="https://api.flutter.dev/flutter/material/TextButton-class.html"><code>TextButton</code></a></li><li><a href="https://api.flutter.dev/flutter/material/FloatingActionButton-class.html"><code>FloatingActionButton</code></a></li><li><a href="https://api.flutter.dev/flutter/material/IconButton-class.html"><code>IconButton</code></a></li><li><a href="https://api.flutter.dev/flutter/material/Radio-class.html"><code>Radio</code></a></li><li><a href="https://api.flutter.dev/flutter/material/ElevatedButton-class.html"><code>ElevatedButton</code></a></li><li><a href="https://api.flutter.dev/flutter/material/Slider-class.html"><code>Slider</code></a></li><li><a href="https://api.flutter.dev/flutter/material/Switch-class.html"><code>Switch</code></a></li><li><a href="https://api.flutter.dev/flutter/material/TextField-class.html"><code>TextField</code></a></li></ul><div class="header-wrapper"><h2 id="resources">Resources</h2><a class="heading-link" href="#resources" aria-label="Link to 'Resources' section">#</a></div><p>The following resources might help when adding interactivity to your app.</p><p><a href="/cookbook/gestures">Gestures</a>, a section in the <a href="/cookbook">Flutter cookbook</a>.</p><dl><dt><a href="/ui#handling-gestures">Handling gestures</a></dt><dd>How to create a button and make it respond to input.</dd><dt><a href="/ui/interactivity/gestures">Gestures in Flutter</a></dt><dd>A description of Flutter's gesture mechanism.</dd><dt><a href="https://api.flutter.dev">Flutter API documentation</a></dt><dd>Reference documentation for all of the Flutter libraries.</dd><dt>Wonderous app <a href="https://wonderous.app//web">running app</a>, <a href="https://github.com/gskinnerTeam/flutter-wonderous-app">repo</a></dt><dd>Flutter showcase app with a custom design and engaging interactions.</dd><dt><a href="https://www.youtube.com/watch?v=dkyY9WCGMi0">Flutter's Layered Design</a> (video)</dt><dd>This video includes information about state and stateless widgets. Presented by Google engineer, Ian Hickson.</dd></dl><p id="page-github-links"><span>Unless stated otherwise, the documentation on this site reflects the latest stable version of Flutter. Page last updated on 2024-08-16.</span> <a href="https://github.com/flutter/website/tree/main/src/content/ui/interactivity/index.md" target="_blank" rel="noopener">View source</a> <span>or </span><a href="https://github.com/flutter/website/issues/new?template=1_page_issue.yml&&page-url=https://docs.flutter.dev/ui/interactivity/&page-source=https://github.com/flutter/website/tree/main/src/content/ui/interactivity/index.md" title="Report an issue with this page" target="_blank" rel="noopener">report an issue</a>.</p></div></main></div></div><footer class="site-footer"><div class="container-fluid"><div class="row"><div class="col-md-12 site-footer__wrapper"><div class="site-footer__logo"><img src="/assets/images/branding/flutter/logo/flutter-mono-81x100.png" alt="Flutter Logo" width="81" height="100"></div><div class="site-footer__content"><ul class="site-footer__link-list"><li><a href="/tos">terms</a></li><li><a href="/brand">brand usage</a></li><li><a href="/security">security</a></li><li><a href="https://www.google.com/intl/en/policies/privacy">privacy</a></li><li><a href="https://esflutter.dev/">español</a></li><li><a href="https://flutter.cn" class="text-nowrap">社区中文资源</a></li><li><a href="https://blog.google/inside-google/company-announcements/standing-with-black-community">We stand in solidarity with the Black community. Black Lives Matter.</a></li></ul><p class="licenses">Except as otherwise noted, this work is licensed under a <a rel="license" href="https://creativecommons.org/licenses/by/4.0">Creative Commons Attribution 4.0 International License</a>, and code samples are licensed under the BSD License.</p></div></div></div></div></footer><script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.0/jquery.min.js" integrity="sha512-3gJwYpMe3QewGELv8k/BX9vcqhryRdzRMxVfq6ngyWXwo03GFEzjsUm8Q7RZcHPHksttq7/GFoxjCVUjkjvPdw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/4.6.2/js/bootstrap.min.js" integrity="sha512-7rusk8kGPFynZWu26OKbTeI+QPoYchtxsmPeBqkHIEXJxeun4yJ4ISYe7C6sz9wdxeE1Gk3VxsIWgCZTc+vX3g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script><script src="/assets/js/tabs.js"></script><script src="/assets/js/archive.js"></script><script src="/assets/js/main.js"></script></body></html>