CINXE.COM
Flutter for Xamarin.Forms developers | Flutter
<!doctype html><html lang="en"><head><meta charset="utf-8"><title>Flutter for Xamarin.Forms developers | 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="Learn how to apply Xamarin.Forms developer knowledge when building Flutter apps."><meta name="twitter:card" content="summary_large_image"><meta name="twitter:site" content="@flutterdev"><meta property="og:title" content="Flutter for Xamarin.Forms developers"><meta property="og:url" content="https://docs.flutter.dev/get-started/flutter-for/xamarin-forms-devs"><meta property="og:description" content="Learn how to apply Xamarin.Forms developer knowledge when building Flutter apps."><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 active collapsible" data-toggle="collapse" href="#header-sidenav-3" role="button" aria-expanded="true" aria-controls="header-sidenav-3">Learn Flutter</a><ul class="nav flex-column flex-nowrap collapse show" 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 active collapsible" data-toggle="collapse" data-target="#header-sidenav-3-4" href="/get-started/flutter-for" role="button" aria-expanded="true" aria-controls="header-sidenav-3-4">From another platform?</a><ul class="nav flex-column flex-nowrap collapse show" 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 active" 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 collapsed collapsible" data-toggle="collapse" href="#header-sidenav-13" role="button" aria-expanded="false" aria-controls="header-sidenav-13">Interactivity</a><ul class="nav flex-column flex-nowrap collapse" id="header-sidenav-13"><li class="nav-item"><a class="nav-link" 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/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 active collapsible" data-toggle="collapse" href="#fixed-sidenav-3" role="button" aria-expanded="true" aria-controls="fixed-sidenav-3">Learn Flutter</a><ul class="nav flex-column flex-nowrap collapse show" 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 active collapsible" data-toggle="collapse" data-target="#fixed-sidenav-3-4" href="/get-started/flutter-for" role="button" aria-expanded="true" aria-controls="fixed-sidenav-3-4">From another platform?</a><ul class="nav flex-column flex-nowrap collapse show" 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 active" 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 collapsed collapsible" data-toggle="collapse" href="#fixed-sidenav-13" role="button" aria-expanded="false" aria-controls="fixed-sidenav-13">Interactivity</a><ul class="nav flex-column flex-nowrap collapse" id="fixed-sidenav-13"><li class="nav-item"><a class="nav-link" 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/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="#project-setup">Project setup</a><ul class="nav"><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-does-the-app-start">How does the app start?</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-you-create-a-page">How do you create a page?</a></li></ul></li><li class="toc-entry nav-item toc-h2"><a class="nav-link" href="#views">Views</a><ul class="nav"><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#what-is-the-equivalent-of-a-page-or-element-in-flutter">What is the equivalent of a Page or Element in Flutter?</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-i-update-widgets">How do I update widgets?</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-i-lay-out-my-widgets-what-is-the-equivalent-of-an-xaml-file">How do I lay out my widgets? What is the equivalent of an XAML file?</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-i-add-or-remove-an-element-from-my-layout">How do I add or remove an Element from my layout?</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-i-animate-a-widget">How do I animate a widget?</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-i-drawpaint-on-the-screen">How do I draw/paint on the screen?</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#where-is-the-widgets-opacity">Where is the widget's opacity?</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-i-build-custom-widgets">How do I build custom widgets?</a></li></ul></li><li class="toc-entry nav-item toc-h2"><a class="nav-link" href="#navigation">Navigation</a><ul class="nav"><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-i-navigate-between-pages">How do I navigate between pages?</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-i-navigate-to-another-app">How do I navigate to another app?</a></li></ul></li><li class="toc-entry nav-item toc-h2"><a class="nav-link" href="#async-ui">Async UI</a><ul class="nav"><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#what-is-the-equivalent-of-device-beginonmainthread-in-flutter">What is the equivalent of Device.BeginOnMainThread() in Flutter?</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-you-move-work-to-a-background-thread">How do you move work to a background thread?</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-i-make-network-requests">How do I make network requests?</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-i-show-the-progress-for-a-long-running-task">How do I show the progress for a long-running task?</a></li></ul></li><li class="toc-entry nav-item toc-h2"><a class="nav-link" href="#project-structure-resources">Project structure & resources</a><ul class="nav"><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#where-do-i-store-my-image-files">Where do I store my image files?</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#where-do-i-store-strings-how-do-i-handle-localization">Where do I store strings? How do I handle localization?</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#where-is-my-project-file">Where is my project file?</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#what-is-the-equivalent-of-nuget-how-do-i-add-dependencies">What is the equivalent of Nuget? How do I add dependencies?</a></li></ul></li><li class="toc-entry nav-item toc-h2"><a class="nav-link" href="#application-lifecycle">Application lifecycle</a><ul class="nav"><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-i-listen-to-application-lifecycle-events">How do I listen to application lifecycle events?</a></li></ul></li><li class="toc-entry nav-item toc-h2"><a class="nav-link" href="#layouts">Layouts</a><ul class="nav"><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#what-is-the-equivalent-of-a-stacklayout">What is the equivalent of a StackLayout?</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#what-is-the-equivalent-of-a-grid">What is the equivalent of a Grid?</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#what-is-the-equivalent-of-a-scrollview">What is the equivalent of a ScrollView?</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-i-handle-landscape-transitions-in-flutter">How do I handle landscape transitions in Flutter?</a></li></ul></li><li class="toc-entry nav-item toc-h2"><a class="nav-link" href="#gesture-detection-and-touch-event-handling">Gesture detection and touch event handling</a><ul class="nav"><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-i-add-gesturerecognizers-to-a-widget-in-flutter">How do I add GestureRecognizers to a widget in Flutter?</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-i-handle-other-gestures-on-widgets">How do I handle other gestures on widgets?</a></li></ul></li><li class="toc-entry nav-item toc-h2"><a class="nav-link" href="#listviews-and-adapters">Listviews and adapters</a><ul class="nav"><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#what-is-the-equivalent-to-a-listview-in-flutter">What is the equivalent to a ListView in Flutter?</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-i-know-which-list-item-has-been-clicked">How do I know which list item has been clicked?</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-i-update-a-listview-dynamically">How do I update a ListView dynamically?</a></li></ul></li><li class="toc-entry nav-item toc-h2"><a class="nav-link" href="#working-with-text">Working with text</a><ul class="nav"><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-i-set-custom-fonts-on-my-text-widgets">How do I set custom fonts on my text widgets?</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-i-style-my-text-widgets">How do I style my text widgets?</a></li></ul></li><li class="toc-entry nav-item toc-h2"><a class="nav-link" href="#form-input">Form input</a><ul class="nav"><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-i-retrieve-user-input">How do I retrieve user input?</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#what-is-the-equivalent-of-a-placeholder-on-an-entry">What is the equivalent of a Placeholder on an Entry?</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-i-show-validation-errors">How do I show validation errors?</a></li></ul></li><li class="toc-entry nav-item toc-h2"><a class="nav-link" href="#flutter-plugins">Flutter plugins</a></li><li class="toc-entry nav-item toc-h2"><a class="nav-link" href="#interacting-with-hardware-third-party-services-and-the-platform">Interacting with hardware, third party services, and the platform</a><ul class="nav"><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-i-interact-with-the-platform-and-with-platform-native-code">How do I interact with the platform, and with platform native code?</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-i-access-the-gps-sensor">How do I access the GPS sensor?</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-i-access-the-camera">How do I access the camera?</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-i-log-in-with-facebook">How do I log in with Facebook?</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-i-use-firebase-features">How do I use Firebase features?</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-i-build-my-own-custom-native-integrations">How do I build my own custom native integrations?</a></li></ul></li><li class="toc-entry nav-item toc-h2"><a class="nav-link" href="#themes-styles">Themes (Styles)</a><ul class="nav"><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-i-theme-my-app">How do I theme my app?</a></li></ul></li><li class="toc-entry nav-item toc-h2"><a class="nav-link" href="#databases-and-local-storage">Databases and local storage</a><ul class="nav"><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-i-access-shared-preferences-or-userdefaults">How do I access shared preferences or UserDefaults?</a></li><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-i-access-sqlite-in-flutter">How do I access SQLite in Flutter?</a></li></ul></li><li class="toc-entry nav-item toc-h2"><a class="nav-link" href="#debugging">Debugging</a><ul class="nav"><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#what-tools-can-i-use-to-debug-my-app-in-flutter">What tools can I use to debug my app in Flutter?</a></li></ul></li><li class="toc-entry nav-item toc-h2"><a class="nav-link" href="#notifications">Notifications</a><ul class="nav"><li class="toc-entry nav-item toc-h3"><a class="nav-link" href="#how-do-i-set-up-push-notifications">How do I set up push notifications?</a></li></ul></li></ul></div><div class="container"><header class="site-content__title" id="site-content-title"><h1>Flutter for Xamarin.Forms developers</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="/get-started" property="item" typeof="WebPage"><span property="name">Get started</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" property="itemListElement" typeof="ListItem"><a href="/get-started/flutter-for" property="item" typeof="WebPage"><span property="name">Flutter for</span></a><meta property="position" content="1"><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="/get-started/flutter-for/xamarin-forms-devs" property="item" typeof="WebPage"><span property="name">Flutter for Xamarin.Forms developers</span></a><meta property="position" content="2"></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="#project-setup">Project setup</a><ul><li class="toc-entry toc-h3"><a href="#how-does-the-app-start">How does the app start?</a></li><li class="toc-entry toc-h3"><a href="#how-do-you-create-a-page">How do you create a page?</a></li></ul></li><li class="toc-entry toc-h2"><a href="#views">Views</a><ul><li class="toc-entry toc-h3"><a href="#what-is-the-equivalent-of-a-page-or-element-in-flutter">What is the equivalent of a Page or Element in Flutter?</a></li><li class="toc-entry toc-h3"><a href="#how-do-i-update-widgets">How do I update widgets?</a></li><li class="toc-entry toc-h3"><a href="#how-do-i-lay-out-my-widgets-what-is-the-equivalent-of-an-xaml-file">How do I lay out my widgets? What is the equivalent of an XAML file?</a></li><li class="toc-entry toc-h3"><a href="#how-do-i-add-or-remove-an-element-from-my-layout">How do I add or remove an Element from my layout?</a></li><li class="toc-entry toc-h3"><a href="#how-do-i-animate-a-widget">How do I animate a widget?</a></li><li class="toc-entry toc-h3"><a href="#how-do-i-drawpaint-on-the-screen">How do I draw/paint on the screen?</a></li><li class="toc-entry toc-h3"><a href="#where-is-the-widgets-opacity">Where is the widget's opacity?</a></li><li class="toc-entry toc-h3"><a href="#how-do-i-build-custom-widgets">How do I build custom widgets?</a></li></ul></li><li class="toc-entry toc-h2"><a href="#navigation">Navigation</a><ul><li class="toc-entry toc-h3"><a href="#how-do-i-navigate-between-pages">How do I navigate between pages?</a></li><li class="toc-entry toc-h3"><a href="#how-do-i-navigate-to-another-app">How do I navigate to another app?</a></li></ul></li><li class="toc-entry toc-h2"><a href="#async-ui">Async UI</a><ul><li class="toc-entry toc-h3"><a href="#what-is-the-equivalent-of-device-beginonmainthread-in-flutter">What is the equivalent of Device.BeginOnMainThread() in Flutter?</a></li><li class="toc-entry toc-h3"><a href="#how-do-you-move-work-to-a-background-thread">How do you move work to a background thread?</a></li><li class="toc-entry toc-h3"><a href="#how-do-i-make-network-requests">How do I make network requests?</a></li><li class="toc-entry toc-h3"><a href="#how-do-i-show-the-progress-for-a-long-running-task">How do I show the progress for a long-running task?</a></li></ul></li><li class="toc-entry toc-h2"><a href="#project-structure-resources">Project structure & resources</a><ul><li class="toc-entry toc-h3"><a href="#where-do-i-store-my-image-files">Where do I store my image files?</a></li><li class="toc-entry toc-h3"><a href="#where-do-i-store-strings-how-do-i-handle-localization">Where do I store strings? How do I handle localization?</a></li><li class="toc-entry toc-h3"><a href="#where-is-my-project-file">Where is my project file?</a></li><li class="toc-entry toc-h3"><a href="#what-is-the-equivalent-of-nuget-how-do-i-add-dependencies">What is the equivalent of Nuget? How do I add dependencies?</a></li></ul></li><li class="toc-entry toc-h2"><a href="#application-lifecycle">Application lifecycle</a><ul><li class="toc-entry toc-h3"><a href="#how-do-i-listen-to-application-lifecycle-events">How do I listen to application lifecycle events?</a></li></ul></li><li class="toc-entry toc-h2"><a href="#layouts">Layouts</a><ul><li class="toc-entry toc-h3"><a href="#what-is-the-equivalent-of-a-stacklayout">What is the equivalent of a StackLayout?</a></li><li class="toc-entry toc-h3"><a href="#what-is-the-equivalent-of-a-grid">What is the equivalent of a Grid?</a></li><li class="toc-entry toc-h3"><a href="#what-is-the-equivalent-of-a-scrollview">What is the equivalent of a ScrollView?</a></li><li class="toc-entry toc-h3"><a href="#how-do-i-handle-landscape-transitions-in-flutter">How do I handle landscape transitions in Flutter?</a></li></ul></li><li class="toc-entry toc-h2"><a href="#gesture-detection-and-touch-event-handling">Gesture detection and touch event handling</a><ul><li class="toc-entry toc-h3"><a href="#how-do-i-add-gesturerecognizers-to-a-widget-in-flutter">How do I add GestureRecognizers to a widget in Flutter?</a></li><li class="toc-entry toc-h3"><a href="#how-do-i-handle-other-gestures-on-widgets">How do I handle other gestures on widgets?</a></li></ul></li><li class="toc-entry toc-h2"><a href="#listviews-and-adapters">Listviews and adapters</a><ul><li class="toc-entry toc-h3"><a href="#what-is-the-equivalent-to-a-listview-in-flutter">What is the equivalent to a ListView in Flutter?</a></li><li class="toc-entry toc-h3"><a href="#how-do-i-know-which-list-item-has-been-clicked">How do I know which list item has been clicked?</a></li><li class="toc-entry toc-h3"><a href="#how-do-i-update-a-listview-dynamically">How do I update a ListView dynamically?</a></li></ul></li><li class="toc-entry toc-h2"><a href="#working-with-text">Working with text</a><ul><li class="toc-entry toc-h3"><a href="#how-do-i-set-custom-fonts-on-my-text-widgets">How do I set custom fonts on my text widgets?</a></li><li class="toc-entry toc-h3"><a href="#how-do-i-style-my-text-widgets">How do I style my text widgets?</a></li></ul></li><li class="toc-entry toc-h2"><a href="#form-input">Form input</a><ul><li class="toc-entry toc-h3"><a href="#how-do-i-retrieve-user-input">How do I retrieve user input?</a></li><li class="toc-entry toc-h3"><a href="#what-is-the-equivalent-of-a-placeholder-on-an-entry">What is the equivalent of a Placeholder on an Entry?</a></li><li class="toc-entry toc-h3"><a href="#how-do-i-show-validation-errors">How do I show validation errors?</a></li></ul></li><li class="toc-entry toc-h2"><a href="#flutter-plugins">Flutter plugins</a></li><li class="toc-entry toc-h2"><a href="#interacting-with-hardware-third-party-services-and-the-platform">Interacting with hardware, third party services, and the platform</a><ul><li class="toc-entry toc-h3"><a href="#how-do-i-interact-with-the-platform-and-with-platform-native-code">How do I interact with the platform, and with platform native code?</a></li><li class="toc-entry toc-h3"><a href="#how-do-i-access-the-gps-sensor">How do I access the GPS sensor?</a></li><li class="toc-entry toc-h3"><a href="#how-do-i-access-the-camera">How do I access the camera?</a></li><li class="toc-entry toc-h3"><a href="#how-do-i-log-in-with-facebook">How do I log in with Facebook?</a></li><li class="toc-entry toc-h3"><a href="#how-do-i-use-firebase-features">How do I use Firebase features?</a></li><li class="toc-entry toc-h3"><a href="#how-do-i-build-my-own-custom-native-integrations">How do I build my own custom native integrations?</a></li></ul></li><li class="toc-entry toc-h2"><a href="#themes-styles">Themes (Styles)</a><ul><li class="toc-entry toc-h3"><a href="#how-do-i-theme-my-app">How do I theme my app?</a></li></ul></li><li class="toc-entry toc-h2"><a href="#databases-and-local-storage">Databases and local storage</a><ul><li class="toc-entry toc-h3"><a href="#how-do-i-access-shared-preferences-or-userdefaults">How do I access shared preferences or UserDefaults?</a></li><li class="toc-entry toc-h3"><a href="#how-do-i-access-sqlite-in-flutter">How do I access SQLite in Flutter?</a></li></ul></li><li class="toc-entry toc-h2"><a href="#debugging">Debugging</a><ul><li class="toc-entry toc-h3"><a href="#what-tools-can-i-use-to-debug-my-app-in-flutter">What tools can I use to debug my app in Flutter?</a></li></ul></li><li class="toc-entry toc-h2"><a href="#notifications">Notifications</a><ul><li class="toc-entry toc-h3"><a href="#how-do-i-set-up-push-notifications">How do I set up push notifications?</a></li></ul></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> <?code-excerpt path-base="get-started/flutter-for/xamarin_devs"?> <p>This document is meant for Xamarin.Forms developers looking to apply their existing knowledge to build mobile apps with Flutter. If you understand the fundamentals of the Xamarin.Forms framework, then you can use this document as a jump start to Flutter development.</p><p>Your Android and iOS knowledge and skill set are valuable when building with Flutter, because Flutter relies on the native operating system configurations, similar to how you would configure your native Xamarin.Forms projects. The Flutter Frameworks is also similar to how you create a single UI, that is used on multiple platforms.</p><p>This document can be used as a cookbook by jumping around and finding questions that are most relevant to your needs.</p><div class="header-wrapper"><h2 id="project-setup">Project setup</h2><a class="heading-link" href="#project-setup" aria-label="Link to 'Project setup' section">#</a></div><div class="header-wrapper"><h3 id="how-does-the-app-start">How does the app start?</h3><a class="heading-link" href="#how-does-the-app-start" aria-label="Link to 'How does the app start?' section">#</a></div><p>For each platform in Xamarin.Forms, you call the <code>LoadApplication</code> method, which creates a new application and starts your app.</p><div class="code-block-wrapper language-csharp"><div class="code-block-body"><span class="code-block-language" title="Language csharp">csharp</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#6200EE">LoadApplication</span><span style="color:#222222">(new </span><span style="color:#0468D7">App</span><span style="color:#222222">());</span></span></code></pre></div></div><p>In Flutter, the default main entry point is <code>main</code> where you load your Flutter app.</p> <?code-excerpt "lib/main.dart (main)"?> <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"> main</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#6200EE"> runApp</span><span style="color:#222222">(</span><span style="color:#BD2314">const</span><span style="color:#0468D7"> MyApp</span><span style="color:#222222">());</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><p>In Xamarin.Forms, you assign a <code>Page</code> to the <code>MainPage</code> property in the <code>Application</code> class.</p><div class="code-block-wrapper language-csharp"><div class="code-block-body"><span class="code-block-language" title="Language csharp">csharp</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#BD2314">public</span><span style="color:#BD2314"> class</span><span style="color:#0468D7"> App</span><span style="color:#222222"> : </span><span style="color:#0468D7">Application</span></span> <span class="line"><span style="color:#222222">{</span></span> <span class="line"><span style="color:#BD2314"> public</span><span style="color:#6200EE"> App</span><span style="color:#222222">()</span></span> <span class="line"><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#222222"> MainPage = new </span><span style="color:#0468D7">ContentPage</span></span> <span class="line"><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#222222"> Content = new </span><span style="color:#0468D7">Label</span></span> <span class="line"><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#222222"> Text = </span><span style="color:#0C7064">"Hello World"</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> HorizontalOptions = LayoutOptions.Center,</span></span> <span class="line"><span style="color:#222222"> VerticalOptions = LayoutOptions.Center</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>In Flutter, "everything is a widget", even the application itself. The following example shows <code>MyApp</code>, a simple application <code>Widget</code>.</p> <?code-excerpt "lib/main.dart (my-app)"?> <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"> 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:#6E6E70"> /// This widget is the root of your application.</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:#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">Text</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#0C7064"> 'Hello World!'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> textDirection: </span><span style="color:#0468D7">TextDirection</span><span style="color:#222222">.ltr,</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><div class="header-wrapper"><h3 id="how-do-you-create-a-page">How do you create a page?</h3><a class="heading-link" href="#how-do-you-create-a-page" aria-label="Link to 'How do you create a page?' section">#</a></div><p>Xamarin.Forms has many types of pages; <code>ContentPage</code> is the most common. In Flutter, you specify an application widget that holds your root page. You can use a <a href="https://api.flutter.dev/flutter/material/MaterialApp-class.html"><code>MaterialApp</code></a> widget, which supports <a href="https://m3.material.io/styles">Material Design</a>, or you can use a <a href="https://api.flutter.dev/flutter/cupertino/CupertinoApp-class.html"><code>CupertinoApp</code></a> widget, which supports an iOS-style app, or you can use the lower level <a href="https://api.flutter.dev/flutter/widgets/WidgetsApp-class.html"><code>WidgetsApp</code></a>, which you can customize in any way you want.</p><p>The following code defines the home page, a stateful widget. In Flutter, all widgets are immutable, but two types of widgets are supported: <em>Stateful</em> and <em>Stateless</em>. Examples of a stateless widget are titles, icons, or images.</p><p>The following example uses <code>MaterialApp</code>, which holds its root page in the <code>home</code> property.</p> <?code-excerpt "lib/page.dart (my-app)"?> <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"> 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:#6E6E70"> /// This widget is the root of your application.</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:#BD2314"> const</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">MyHomePage</span><span style="color:#222222">(title: </span><span style="color:#0C7064">'Flutter Demo Home Page'</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>From here, your actual first page is another <code>Widget</code>, in which you create your state.</p><p>A <em>Stateful</em> widget, such as <code>MyHomePage</code> below, consists of two parts. The first part, which is itself immutable, creates a <code>State</code> object that holds the state of the object. The <code>State</code> object persists over the life of the widget.</p> <?code-excerpt "lib/page.dart (my-home-page)"?> <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"> MyHomePage</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"> MyHomePage</span><span style="color:#222222">({</span><span style="color:#BD2314">super</span><span style="color:#222222">.key, </span><span style="color:#BD2314">required</span><span style="color:#BD2314"> this</span><span style="color:#222222">.title});</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> String</span><span style="color:#222222"> title;</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">MyHomePage</span><span style="color:#222222">> </span><span style="color:#6200EE">createState</span><span style="color:#222222">() => </span><span style="color:#0468D7">_MyHomePageState</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><p>The <code>State</code> object implements the <code>build()</code> method for the stateful widget.</p><p>When the state of the widget tree changes, call <code>setState()</code>, which triggers a build of that portion of the UI. Make sure to call <code>setState()</code> only when necessary, and only on the part of the widget tree that has changed, or it can result in poor UI performance.</p> <?code-excerpt "lib/page.dart (my-home-page-state)"?> <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"> _MyHomePageState</span><span style="color:#BD2314"> extends</span><span style="color:#0468D7"> State</span><span style="color:#222222"><</span><span style="color:#0468D7">MyHomePage</span><span style="color:#222222">> {</span></span> <span class="line"><span style="color:#0468D7"> int</span><span style="color:#222222"> _counter = </span><span style="color:#0C7064">0</span><span style="color:#222222">;</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> void</span><span style="color:#6200EE"> _incrementCounter</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"> _counter++;</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"> 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:#6E6E70"> // Take the value from the MyHomePage object that was created by</span></span> <span class="line"><span style="color:#6E6E70"> // the App.build method, and use it to set the appbar title.</span></span> <span class="line"><span style="color:#222222"> title: </span><span style="color:#0468D7">Text</span><span style="color:#222222">(widget.title),</span></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#222222"> body: </span><span style="color:#0468D7">Center</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#6E6E70"> // Center is a layout widget. It takes a single child and positions it</span></span> <span class="line"><span style="color:#6E6E70"> // in the middle of the parent.</span></span> <span class="line"><span style="color:#222222"> child: </span><span style="color:#0468D7">Column</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> mainAxisAlignment: </span><span style="color:#0468D7">MainAxisAlignment</span><span style="color:#222222">.center,</span></span> <span class="line"><span style="color:#222222"> children: <</span><span style="color:#0468D7">Widget</span><span style="color:#222222">>[</span></span> <span class="line"><span style="color:#BD2314"> const</span><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#0C7064"> 'You have pushed the button this many times:'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#0C7064"> '</span><span style="color:#0C7064">$</span><span style="color:#222222">_counter</span><span style="color:#0C7064">'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> style: </span><span style="color:#0468D7">Theme</span><span style="color:#222222">.</span><span style="color:#6200EE">of</span><span style="color:#222222">(context).textTheme.headlineMedium,</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"> floatingActionButton: </span><span style="color:#0468D7">FloatingActionButton</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> onPressed: _incrementCounter,</span></span> <span class="line"><span style="color:#222222"> tooltip: </span><span style="color:#0C7064">'Increment'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> child: </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">.add),</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>In Flutter, the UI (also known as widget tree), is immutable, meaning you can't change its state once it's built. You change fields in your <code>State</code> class, then call <code>setState()</code> to rebuild the entire widget tree again.</p><p>This way of generating UI is different from Xamarin.Forms, but there are many benefits to this approach.</p><div class="header-wrapper"><h2 id="views">Views</h2><a class="heading-link" href="#views" aria-label="Link to 'Views' section">#</a></div><div class="header-wrapper"><h3 id="what-is-the-equivalent-of-a-page-or-element-in-flutter">What is the equivalent of a Page or Element in Flutter?</h3><a class="heading-link" href="#what-is-the-equivalent-of-a-page-or-element-in-flutter" aria-label="Link to 'What is the equivalent of a Page or Element in Flutter?' section">#</a></div><aside class="alert alert-secondary"><div class="alert-header"><span></span></div><div class="alert-content"><p>How is react-style, or <em>declarative</em>, programming different from the traditional imperative style? For a comparison, see <a href="/get-started/flutter-for/declarative">Introduction to declarative UI</a>.</p></div></aside><p><code>ContentPage</code>, <code>TabbedPage</code>, <code>FlyoutPage</code> are all types of pages you might use in a Xamarin.Forms application. These pages would then hold <code>Element</code>s to display the various controls. In Xamarin.Forms an <code>Entry</code> or <code>Button</code> are examples of an <code>Element</code>.</p><p>In Flutter, almost everything is a widget. A <code>Page</code>, called a <code>Route</code> in Flutter, is a widget. Buttons, progress bars, and animation controllers are all widgets. When building a route, you create a widget tree.</p><p>Flutter includes the <a href="/ui/widgets/material">Material Components</a> library. These are widgets that implement the <a href="https://m3.material.io/styles">Material Design guidelines</a>. Material Design is a flexible design system <a href="https://m2.material.io/design/platform-guidance/cross-platform-adaptation.html#cross-platform-guidelines">optimized for all platforms</a>, including iOS.</p><p>But Flutter is flexible and expressive enough to implement any design language. For example, on iOS, you can use the <a href="/ui/widgets/cupertino">Cupertino widgets</a> to produce an interface that looks like <a href="https://developer.apple.com/design/resources/">Apple's iOS design language</a>.</p><div class="header-wrapper"><h3 id="how-do-i-update-widgets">How do I update widgets?</h3><a class="heading-link" href="#how-do-i-update-widgets" aria-label="Link to 'How do I update widgets?' section">#</a></div><p>In Xamarin.Forms, each <code>Page</code> or <code>Element</code> is a stateful class, that has properties and methods. You update your <code>Element</code> by updating a property, and this is propagated down to the native control.</p><p>In Flutter, <code>Widget</code>s are immutable and you can't directly update them by changing a property, instead you have to work with the widget's state.</p><p>This is where the concept of Stateful vs Stateless widgets comes from. A <code>StatelessWidget</code> is just what it sounds like— a widget with no state information.</p><p><code>StatelessWidgets</code> are useful when the part of the user interface you are describing doesn't depend on anything other than the configuration information in the object.</p><p>For example, in Xamarin.Forms, this is similar to placing an <code>Image</code> with your logo. The logo is not going to change during runtime, so use a <code>StatelessWidget</code> in Flutter.</p><p>If you want to dynamically change the UI based on data received after making an HTTP call or a user interaction, then you have to work with <code>StatefulWidget</code> and tell the Flutter framework that the widget's <code>State</code> has been updated, so it can update that widget.</p><p>The important thing to note here is at the core both stateless and stateful widgets behave the same. They rebuild every frame, the difference is the <code>StatefulWidget</code> has a <code>State</code> object that stores state data across frames and restores it.</p><p>If you are in doubt, then always remember this rule: if a widget changes (because of user interactions, for example) it's stateful. However, if a widget reacts to change, the containing parent widget can still be stateless if it doesn't itself react to change.</p><p>The following example shows how to use a <code>StatelessWidget</code>. A common <code>StatelessWidget</code> is the <code>Text</code> widget. If you look at the implementation of the <code>Text</code> widget you'll find it subclasses <code>StatelessWidget</code>.</p> <?code-excerpt "lib/views.dart (text)" replace="/return //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">const</span><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#0C7064"> 'I like Flutter!'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> style: </span><span style="color:#0468D7">TextStyle</span><span style="color:#222222">(fontWeight: </span><span style="color:#0468D7">FontWeight</span><span style="color:#222222">.bold),</span></span> <span class="line"><span style="color:#222222">);</span></span></code></pre></div></div><p>As you can see, the <code>Text</code> widget has no state information associated with it, it renders what is passed in its constructors and nothing more.</p><p>But, what if you want to make "I Like Flutter" change dynamically, for example, when clicking a <code>FloatingActionButton</code>?</p><p>To achieve this, wrap the <code>Text</code> widget in a <code>StatefulWidget</code> and update it when the user clicks the button, as shown in the following example:</p> <?code-excerpt "lib/views_stateful.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:#BD2314">void</span><span style="color:#6200EE"> main</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#6200EE"> runApp</span><span style="color:#222222">(</span><span style="color:#BD2314">const</span><span style="color:#0468D7"> SampleApp</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"> SampleApp</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:#6E6E70"> /// This widget is the root of your application.</span></span> <span class="line"><span style="color:#BD2314"> const</span><span style="color:#0468D7"> SampleApp</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:#BD2314"> const</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">'Sample App'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> home: </span><span style="color:#0468D7">SampleAppPage</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> <span class="line"><span style="color:#BD2314">class</span><span style="color:#0468D7"> SampleAppPage</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"> SampleAppPage</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">SampleAppPage</span><span style="color:#222222">> </span><span style="color:#6200EE">createState</span><span style="color:#222222">() => </span><span style="color:#0468D7">_SampleAppPageState</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"> _SampleAppPageState</span><span style="color:#BD2314"> extends</span><span style="color:#0468D7"> State</span><span style="color:#222222"><</span><span style="color:#0468D7">SampleAppPage</span><span style="color:#222222">> {</span></span> <span class="line"><span style="color:#6E6E70"> /// Default placeholder text</span></span> <span class="line"><span style="color:#0468D7"> String</span><span style="color:#222222"> textToShow = </span><span style="color:#0C7064">'I Like Flutter'</span><span style="color:#222222">;</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> void</span><span style="color:#6200EE"> _updateText</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:#6E6E70"> // Update the text</span></span> <span class="line"><span style="color:#222222"> textToShow = </span><span style="color:#0C7064">'Flutter is Awesome!'</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"> @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"> 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">(title: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'Sample App'</span><span style="color:#222222">)),</span></span> <span class="line"><span style="color:#222222"> body: </span><span style="color:#0468D7">Center</span><span style="color:#222222">(child: </span><span style="color:#0468D7">Text</span><span style="color:#222222">(textToShow)),</span></span> <span class="line"><span style="color:#222222"> floatingActionButton: </span><span style="color:#0468D7">FloatingActionButton</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> onPressed: _updateText,</span></span> <span class="line"><span style="color:#222222"> tooltip: </span><span style="color:#0C7064">'Update Text'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> child: </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">.update),</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><div class="header-wrapper"><h3 id="how-do-i-lay-out-my-widgets-what-is-the-equivalent-of-an-xaml-file">How do I lay out my widgets? What is the equivalent of an XAML file?</h3><a class="heading-link" href="#how-do-i-lay-out-my-widgets-what-is-the-equivalent-of-an-xaml-file" aria-label="Link to 'How do I lay out my widgets? What is the equivalent of an XAML file?' section">#</a></div><p>In Xamarin.Forms, most developers write layouts in XAML, though sometimes in C#. In Flutter, you write your layouts with a widget tree in code.</p><p>The following example shows how to display a simple widget with padding:</p> <?code-excerpt "lib/padding.dart (padding)"?> <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">@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"> 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">(title: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'Sample App'</span><span style="color:#222222">)),</span></span> <span class="line"><span style="color:#222222"> body: </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">ElevatedButton</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> style: </span><span style="color:#0468D7">ElevatedButton</span><span style="color:#222222">.</span><span style="color:#6200EE">styleFrom</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">only</span><span style="color:#222222">(left: </span><span style="color:#0C7064">20</span><span style="color:#222222">, right: </span><span style="color:#0C7064">30</span><span style="color:#222222">),</span></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#222222"> onPressed: () {},</span></span> <span class="line"><span style="color:#222222"> child: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'Hello'</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></code></pre></div></div><p>You can view the layouts that Flutter has to offer in the <a href="/ui/widgets/layout">widget catalog</a>.</p><div class="header-wrapper"><h3 id="how-do-i-add-or-remove-an-element-from-my-layout">How do I add or remove an Element from my layout?</h3><a class="heading-link" href="#how-do-i-add-or-remove-an-element-from-my-layout" aria-label="Link to 'How do I add or remove an Element from my layout?' section">#</a></div><p>In Xamarin.Forms, you had to remove or add an <code>Element</code> in code. This involved either setting the <code>Content</code> property or calling <code>Add()</code> or <code>Remove()</code> if it was a list.</p><p>In Flutter, because widgets are immutable there is no direct equivalent. Instead, you can pass a function to the parent that returns a widget, and control that child's creation with a boolean flag.</p><p>The following example shows how to toggle between two widgets when the user clicks the <code>FloatingActionButton</code>:</p> <?code-excerpt "lib/views.dart (add-remove-element)"?> <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"> SampleApp</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:#6E6E70"> /// This widget is the root of your application.</span></span> <span class="line"><span style="color:#BD2314"> const</span><span style="color:#0468D7"> SampleApp</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:#BD2314"> const</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">'Sample App'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> home: </span><span style="color:#0468D7">SampleAppPage</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> <span class="line"><span style="color:#BD2314">class</span><span style="color:#0468D7"> SampleAppPage</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"> SampleAppPage</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">SampleAppPage</span><span style="color:#222222">> </span><span style="color:#6200EE">createState</span><span style="color:#222222">() => </span><span style="color:#0468D7">_SampleAppPageState</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"> _SampleAppPageState</span><span style="color:#BD2314"> extends</span><span style="color:#0468D7"> State</span><span style="color:#222222"><</span><span style="color:#0468D7">SampleAppPage</span><span style="color:#222222">> {</span></span> <span class="line"><span style="color:#6E6E70"> /// Default value for toggle</span></span> <span class="line"><span style="color:#0468D7"> bool</span><span style="color:#222222"> toggle = </span><span style="color:#0C7064">true</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#BD2314"> void</span><span style="color:#6200EE"> _toggle</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"> toggle = !toggle;</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:#0468D7"> Widget</span><span style="color:#6200EE"> _getToggleChild</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#BD2314"> if</span><span style="color:#222222"> (toggle) {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#BD2314"> const</span><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'Toggle One'</span><span style="color:#222222">);</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#0468D7"> CupertinoButton</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> onPressed: () {},</span></span> <span class="line"><span style="color:#222222"> child: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'Toggle Two'</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"> @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"> 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">(title: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'Sample App'</span><span style="color:#222222">)),</span></span> <span class="line"><span style="color:#222222"> body: </span><span style="color:#0468D7">Center</span><span style="color:#222222">(child: </span><span style="color:#6200EE">_getToggleChild</span><span style="color:#222222">()),</span></span> <span class="line"><span style="color:#222222"> floatingActionButton: </span><span style="color:#0468D7">FloatingActionButton</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> onPressed: _toggle,</span></span> <span class="line"><span style="color:#222222"> tooltip: </span><span style="color:#0C7064">'Update Text'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> child: </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">.update),</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><div class="header-wrapper"><h3 id="how-do-i-animate-a-widget">How do I animate a widget?</h3><a class="heading-link" href="#how-do-i-animate-a-widget" aria-label="Link to 'How do I animate a widget?' section">#</a></div><p>In Xamarin.Forms, you create simple animations using ViewExtensions that include methods such as <code>FadeTo</code> and <code>TranslateTo</code>. You would use these methods on a view to perform the required animations.</p><div class="code-block-wrapper language-xml"><div class="code-block-body"><span class="code-block-language" title="Language xml">xml</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#222222"><</span><span style="color:#0468D7">Image</span><span style="color:#6200EE"> Source</span><span style="color:#222222">=</span><span style="color:#0C7064">"{Binding MyImage}"</span><span style="color:#6200EE"> x</span><span style="color:#222222">:</span><span style="color:#6200EE">Name</span><span style="color:#222222">=</span><span style="color:#0C7064">"myImage"</span><span style="color:#222222"> /></span></span></code></pre></div></div><p>Then in code behind, or a behavior, this would fade in the image, over a 1-second period.</p><div class="code-block-wrapper language-csharp"><div class="code-block-body"><span class="code-block-language" title="Language csharp">csharp</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#222222">myImage.</span><span style="color:#6200EE">FadeTo</span><span style="color:#222222">(</span><span style="color:#0C7064">0</span><span style="color:#222222">, </span><span style="color:#0C7064">1000</span><span style="color:#222222">);</span></span></code></pre></div></div><p>In Flutter, you animate widgets using the animation library by wrapping widgets inside an animated widget. Use an <code>AnimationController</code>, which is an <code>Animation<double></code> that can pause, seek, stop and reverse the animation. It requires a <code>Ticker</code> that signals when vsync happens, and produces a linear interpolation between 0 and 1 on each frame while it's running. You then create one or more<code>Animation</code>s and attach them to the controller.</p><p>For example, you might use <code>CurvedAnimation</code> to implement an animation along an interpolated curve. In this sense, the controller is the "master" source of the animation progress and the <code>CurvedAnimation</code> computes the curve that replaces the controller's default linear motion. Like widgets, animations in Flutter work with composition.</p><p>When building the widget tree, you assign the <code>Animation</code> to an animated property of a widget, such as the opacity of a <code>FadeTransition</code>, and tell the controller to start the animation.</p><p>The following example shows how to write a <code>FadeTransition</code> that fades the widget into a logo when you press the <code>FloatingActionButton</code>:</p> <?code-excerpt "lib/animation.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:#BD2314">void</span><span style="color:#6200EE"> main</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#6200EE"> runApp</span><span style="color:#222222">(</span><span style="color:#BD2314">const</span><span style="color:#0468D7"> FadeAppTest</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"> FadeAppTest</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:#6E6E70"> /// This widget is the root of your application.</span></span> <span class="line"><span style="color:#BD2314"> const</span><span style="color:#0468D7"> FadeAppTest</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:#BD2314"> const</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">'Fade Demo'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> home: </span><span style="color:#0468D7">MyFadeTest</span><span style="color:#222222">(title: </span><span style="color:#0C7064">'Fade Demo'</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> <span class="line"><span style="color:#BD2314">class</span><span style="color:#0468D7"> MyFadeTest</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"> MyFadeTest</span><span style="color:#222222">({</span><span style="color:#BD2314">super</span><span style="color:#222222">.key, </span><span style="color:#BD2314">required</span><span style="color:#BD2314"> this</span><span style="color:#222222">.title});</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> String</span><span style="color:#222222"> title;</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">MyFadeTest</span><span style="color:#222222">> </span><span style="color:#6200EE">createState</span><span style="color:#222222">() => </span><span style="color:#0468D7">_MyFadeTest</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"> _MyFadeTest</span><span style="color:#BD2314"> extends</span><span style="color:#0468D7"> State</span><span style="color:#222222"><</span><span style="color:#0468D7">MyFadeTest</span><span style="color:#222222">> </span><span style="color:#BD2314">with</span><span style="color:#0468D7"> TickerProviderStateMixin</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#BD2314"> late</span><span style="color:#BD2314"> final</span><span style="color:#0468D7"> AnimationController</span><span style="color:#222222"> controller;</span></span> <span class="line"><span style="color:#BD2314"> late</span><span style="color:#BD2314"> final</span><span style="color:#0468D7"> CurvedAnimation</span><span style="color:#222222"> curve;</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> @override</span></span> <span class="line"><span style="color:#BD2314"> void</span><span style="color:#6200EE"> initState</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#BD2314"> super</span><span style="color:#222222">.</span><span style="color:#6200EE">initState</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#222222"> controller = </span><span style="color:#0468D7">AnimationController</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> duration: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> Duration</span><span style="color:#222222">(milliseconds: </span><span style="color:#0C7064">2000</span><span style="color:#222222">),</span></span> <span class="line"><span style="color:#222222"> vsync: </span><span style="color:#BD2314">this</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> );</span></span> <span class="line"><span style="color:#222222"> curve = </span><span style="color:#0468D7">CurvedAnimation</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> parent: controller,</span></span> <span class="line"><span style="color:#222222"> curve: </span><span style="color:#0468D7">Curves</span><span style="color:#222222">.easeIn,</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"> 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">(title: </span><span style="color:#0468D7">Text</span><span style="color:#222222">(widget.title)),</span></span> <span class="line"><span style="color:#222222"> body: </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">FadeTransition</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> opacity: curve,</span></span> <span class="line"><span style="color:#222222"> child: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> FlutterLogo</span><span style="color:#222222">(size: </span><span style="color:#0C7064">100</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"> floatingActionButton: </span><span style="color:#0468D7">FloatingActionButton</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> onPressed: () {</span></span> <span class="line"><span style="color:#222222"> controller.</span><span style="color:#6200EE">forward</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#222222"> },</span></span> <span class="line"><span style="color:#222222"> tooltip: </span><span style="color:#0C7064">'Fade'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> child: </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">.brush),</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>For more information, see <a href="/ui/widgets/animation">Animation & Motion widgets</a>, the <a href="/ui/animations/tutorial">Animations tutorial</a>, and the <a href="/ui/animations">Animations overview</a>.</p><div class="header-wrapper"><h3 id="how-do-i-drawpaint-on-the-screen">How do I draw/paint on the screen?</h3><a class="heading-link" href="#how-do-i-drawpaint-on-the-screen" aria-label="Link to 'How do I draw/paint on the screen?' section">#</a></div><p>Xamarin.Forms never had a built-in way to draw directly on the screen. Many would use SkiaSharp, if they needed a custom image drawn. In Flutter, you have direct access to the Skia Canvas and can easily draw on screen.</p><p>Flutter has two classes that help you draw to the canvas: <code>CustomPaint</code> and <code>CustomPainter</code>, the latter of which implements your algorithm to draw to the canvas.</p><p>To learn how to implement a signature painter in Flutter, see Collin's answer on <a href="https://stackoverflow.com/questions/46241071/create-signature-area-for-mobile-app-in-dart-flutter">Custom Paint</a>.</p> <?code-excerpt "lib/draw.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:#BD2314">void</span><span style="color:#6200EE"> main</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#6200EE"> runApp</span><span style="color:#222222">(</span><span style="color:#BD2314">const</span><span style="color:#0468D7"> MaterialApp</span><span style="color:#222222">(home: </span><span style="color:#0468D7">DemoApp</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"> DemoApp</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"> DemoApp</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 style="color:#BD2314">const</span><span style="color:#0468D7"> Scaffold</span><span style="color:#222222">(body: </span><span style="color:#0468D7">Signature</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"> Signature</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"> Signature</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"> SignatureState</span><span style="color:#6200EE"> createState</span><span style="color:#222222">() => </span><span style="color:#0468D7">SignatureState</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"> SignatureState</span><span style="color:#BD2314"> extends</span><span style="color:#0468D7"> State</span><span style="color:#222222"><</span><span style="color:#0468D7">Signature</span><span style="color:#222222">> {</span></span> <span class="line"><span style="color:#0468D7"> List</span><span style="color:#222222"><</span><span style="color:#0468D7">Offset</span><span style="color:#222222">?> _points = <</span><span style="color:#0468D7">Offset</span><span style="color:#222222">?>[];</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> void</span><span style="color:#6200EE"> _onPanUpdate</span><span style="color:#222222">(</span><span style="color:#0468D7">DragUpdateDetails</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:#BD2314"> final</span><span style="color:#0468D7"> RenderBox</span><span style="color:#222222"> referenceBox = context.</span><span style="color:#6200EE">findRenderObject</span><span style="color:#222222">() </span><span style="color:#BD2314">as</span><span style="color:#0468D7"> RenderBox</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> Offset</span><span style="color:#222222"> localPosition = referenceBox.</span><span style="color:#6200EE">globalToLocal</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> details.globalPosition,</span></span> <span class="line"><span style="color:#222222"> );</span></span> <span class="line"><span style="color:#222222"> _points = </span><span style="color:#0468D7">List</span><span style="color:#222222">.</span><span style="color:#6200EE">from</span><span style="color:#222222">(_points)..</span><span style="color:#6200EE">add</span><span style="color:#222222">(localPosition);</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"> onPanUpdate: _onPanUpdate,</span></span> <span class="line"><span style="color:#222222"> onPanEnd: (details) => _points.</span><span style="color:#6200EE">add</span><span style="color:#222222">(</span><span style="color:#0C7064">null</span><span style="color:#222222">),</span></span> <span class="line"><span style="color:#222222"> child: </span><span style="color:#0468D7">CustomPaint</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> painter: </span><span style="color:#0468D7">SignaturePainter</span><span style="color:#222222">(_points),</span></span> <span class="line"><span style="color:#222222"> size: </span><span style="color:#0468D7">Size</span><span style="color:#222222">.infinite,</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:#BD2314">class</span><span style="color:#0468D7"> SignaturePainter</span><span style="color:#BD2314"> extends</span><span style="color:#0468D7"> CustomPainter</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#BD2314"> const</span><span style="color:#0468D7"> SignaturePainter</span><span style="color:#222222">(</span><span style="color:#BD2314">this</span><span style="color:#222222">.points);</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> List</span><span style="color:#222222"><</span><span style="color:#0468D7">Offset</span><span style="color:#222222">?> points;</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> @override</span></span> <span class="line"><span style="color:#BD2314"> void</span><span style="color:#6200EE"> paint</span><span style="color:#222222">(</span><span style="color:#0468D7">Canvas</span><span style="color:#222222"> canvas, </span><span style="color:#0468D7">Size</span><span style="color:#222222"> size) {</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> Paint</span><span style="color:#222222"> paint = </span><span style="color:#0468D7">Paint</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">.black</span></span> <span class="line"><span style="color:#222222"> ..strokeCap = </span><span style="color:#0468D7">StrokeCap</span><span style="color:#222222">.round</span></span> <span class="line"><span style="color:#222222"> ..strokeWidth = </span><span style="color:#0C7064">5</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#BD2314"> for</span><span style="color:#222222"> (</span><span style="color:#0468D7">int</span><span style="color:#222222"> i = </span><span style="color:#0C7064">0</span><span style="color:#222222">; i < points.length - </span><span style="color:#0C7064">1</span><span style="color:#222222">; i++) {</span></span> <span class="line"><span style="color:#BD2314"> if</span><span style="color:#222222"> (points[i] != </span><span style="color:#0C7064">null</span><span style="color:#222222"> && points[i + </span><span style="color:#0C7064">1</span><span style="color:#222222">] != </span><span style="color:#0C7064">null</span><span style="color:#222222">) {</span></span> <span class="line"><span style="color:#222222"> canvas.</span><span style="color:#6200EE">drawLine</span><span style="color:#222222">(points[i]!, points[i + </span><span style="color:#0C7064">1</span><span style="color:#222222">]!, paint);</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:#BD2314"> @override</span></span> <span class="line"><span style="color:#0468D7"> bool</span><span style="color:#6200EE"> shouldRepaint</span><span style="color:#222222">(</span><span style="color:#0468D7">SignaturePainter</span><span style="color:#222222"> oldDelegate) =></span></span> <span class="line"><span style="color:#222222"> oldDelegate.points != points;</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><div class="header-wrapper"><h3 id="where-is-the-widgets-opacity">Where is the widget's opacity?</h3><a class="heading-link" href="#where-is-the-widgets-opacity" aria-label="Link to 'Where is the widget's opacity?' section">#</a></div><p>On Xamarin.Forms, all <code>VisualElement</code>s have an Opacity. In Flutter, you need to wrap a widget in an <a href="https://api.flutter.dev/flutter/widgets/Opacity-class.html"><code>Opacity</code> widget</a> to accomplish this.</p><div class="header-wrapper"><h3 id="how-do-i-build-custom-widgets">How do I build custom widgets?</h3><a class="heading-link" href="#how-do-i-build-custom-widgets" aria-label="Link to 'How do I build custom widgets?' section">#</a></div><p>In Xamarin.Forms, you typically subclass <code>VisualElement</code>, or use a pre-existing <code>VisualElement</code>, to override and implement methods that achieve the desired behavior.</p><p>In Flutter, build a custom widget by <a href="/resources/architectural-overview#composition">composing</a> smaller widgets (instead of extending them). It is somewhat similar to implementing a custom control based off a <code>Grid</code> with numerous <code>VisualElement</code>s added in, while extending with custom logic.</p><p>For example, how do you build a <code>CustomButton</code> that takes a label in the constructor? Create a CustomButton that composes a <code>ElevatedButton</code> with a label, rather than by extending <code>ElevatedButton</code>:</p> <?code-excerpt "lib/custom_button.dart (custom-button)"?> <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"> CustomButton</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"> CustomButton</span><span style="color:#222222">(</span><span style="color:#BD2314">this</span><span style="color:#222222">.label, {</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"> final</span><span style="color:#0468D7"> String</span><span style="color:#222222"> label;</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"> ElevatedButton</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> onPressed: () {},</span></span> <span class="line"><span style="color:#222222"> child: </span><span style="color:#0468D7">Text</span><span style="color:#222222">(label),</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>Then use <code>CustomButton</code>, just as you'd use any other Flutter widget:</p> <?code-excerpt "lib/custom_button.dart (use-custom-button)"?> <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">@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:#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">CustomButton</span><span style="color:#222222">(</span><span style="color:#0C7064">'Hello'</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><div class="header-wrapper"><h2 id="navigation">Navigation</h2><a class="heading-link" href="#navigation" aria-label="Link to 'Navigation' section">#</a></div><div class="header-wrapper"><h3 id="how-do-i-navigate-between-pages">How do I navigate between pages?</h3><a class="heading-link" href="#how-do-i-navigate-between-pages" aria-label="Link to 'How do I navigate between pages?' section">#</a></div><p>In Xamarin.Forms, the <code>NavigationPage</code> class provides a hierarchical navigation experience where the user is able to navigate through pages, forwards and backwards.</p><p>Flutter has a similar implementation, using a <code>Navigator</code> and <code>Routes</code>. A <code>Route</code> is an abstraction for a <code>Page</code> of an app, and a <code>Navigator</code> is a <a href="/resources/architectural-overview#widgets">widget</a> that manages routes.</p><p>A route roughly maps to a <code>Page</code>. The navigator works in a similar way to the Xamarin.Forms <code>NavigationPage</code>, in that it can <code>push()</code> and <code>pop()</code> routes depending on whether you want to navigate to, or back from, a view.</p><p>To navigate between pages, you have a couple options:</p><ul><li>Specify a <code>Map</code> of route names. (<code>MaterialApp</code>)</li><li>Directly navigate to a route. (<code>WidgetsApp</code>)</li></ul><p>The following example builds a <code>Map</code>.</p> <?code-excerpt "lib/navigation.dart (main)"?> <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"> main</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#6200EE"> runApp</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#0468D7"> MaterialApp</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> home: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> MyAppHome</span><span style="color:#222222">(), </span><span style="color:#6E6E70">// becomes the route named '/'</span></span> <span class="line"><span style="color:#222222"> routes: <</span><span style="color:#0468D7">String</span><span style="color:#222222">, </span><span style="color:#0468D7">WidgetBuilder</span><span style="color:#222222">>{</span></span> <span class="line"><span style="color:#0C7064"> '/a'</span><span style="color:#222222">: (context) => </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> MyPage</span><span style="color:#222222">(title: </span><span style="color:#0C7064">'page A'</span><span style="color:#222222">),</span></span> <span class="line"><span style="color:#0C7064"> '/b'</span><span style="color:#222222">: (context) => </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> MyPage</span><span style="color:#222222">(title: </span><span style="color:#0C7064">'page B'</span><span style="color:#222222">),</span></span> <span class="line"><span style="color:#0C7064"> '/c'</span><span style="color:#222222">: (context) => </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> MyPage</span><span style="color:#222222">(title: </span><span style="color:#0C7064">'page C'</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></code></pre></div></div><p>Navigate to a route by pushing its name to the <code>Navigator</code>.</p> <?code-excerpt "lib/navigation.dart (push-named)"?> <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:#0468D7">Navigator</span><span style="color:#222222">.</span><span style="color:#6200EE">of</span><span style="color:#222222">(context).</span><span style="color:#6200EE">pushNamed</span><span style="color:#222222">(</span><span style="color:#0C7064">'/b'</span><span style="color:#222222">);</span></span></code></pre></div></div><p>The <code>Navigator</code> is a stack that manages your app's routes. Pushing a route to the stack moves to that route. Popping a route from the stack, returns to the previous route. This is done by awaiting on the <code>Future</code> returned by <code>push()</code>.</p><p><code>async</code>/<code>await</code> is very similar to the .NET implementation and is explained in more detail in <a href="#async-ui">Async UI</a>.</p><p>For example, to start a <code>location</code> route that lets the user select their location, you might do the following:</p> <?code-excerpt "lib/navigation.dart (await)"?> <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:#0468D7">Object</span><span style="color:#222222">? coordinates = </span><span style="color:#BD2314">await</span><span style="color:#0468D7"> Navigator</span><span style="color:#222222">.</span><span style="color:#6200EE">of</span><span style="color:#222222">(context).</span><span style="color:#6200EE">pushNamed</span><span style="color:#222222">(</span><span style="color:#0C7064">'/location'</span><span style="color:#222222">);</span></span></code></pre></div></div><p>And then, inside your 'location' route, once the user has selected their location, pop the stack with the result:</p> <?code-excerpt "lib/navigation.dart (pop-location)"?> <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:#0468D7">Navigator</span><span style="color:#222222">.</span><span style="color:#6200EE">of</span><span style="color:#222222">(context).</span><span style="color:#6200EE">pop</span><span style="color:#222222">({</span><span style="color:#0C7064">'lat'</span><span style="color:#222222">: </span><span style="color:#0C7064">43.821757</span><span style="color:#222222">, </span><span style="color:#0C7064">'long'</span><span style="color:#222222">: -</span><span style="color:#0C7064">79.226392</span><span style="color:#222222">});</span></span></code></pre></div></div><div class="header-wrapper"><h3 id="how-do-i-navigate-to-another-app">How do I navigate to another app?</h3><a class="heading-link" href="#how-do-i-navigate-to-another-app" aria-label="Link to 'How do I navigate to another app?' section">#</a></div><p>In Xamarin.Forms, to send the user to another application, you use a specific URI scheme, using <code>Device.OpenUrl("mailto://")</code>.</p><p>To implement this functionality in Flutter, create a native platform integration, or use an <a href="https://pub.dev/flutter">existing plugin</a>, such as<a href="https://pub.dev/packages/url_launcher"><code>url_launcher</code></a>, available with many other packages on <a href="https://pub.dev">pub.dev</a>.</p><div class="header-wrapper"><h2 id="async-ui">Async UI</h2><a class="heading-link" href="#async-ui" aria-label="Link to 'Async UI' section">#</a></div><div class="header-wrapper"><h3 id="what-is-the-equivalent-of-device-beginonmainthread-in-flutter">What is the equivalent of Device.BeginOnMainThread() in Flutter?</h3><a class="heading-link" href="#what-is-the-equivalent-of-device-beginonmainthread-in-flutter" aria-label="Link to 'What is the equivalent of Device.BeginOnMainThread() in Flutter?' section">#</a></div><p>Dart has a single-threaded execution model, with support for <code>Isolate</code>s (a way to run Dart codes on another thread), an event loop, and asynchronous programming. Unless you spawn an <code>Isolate</code>, your Dart code runs in the main UI thread and is driven by an event loop.</p><p>Dart's single-threaded model doesn't mean you need to run everything as a blocking operation that causes the UI to freeze. Much like Xamarin.Forms, you need to keep the UI thread free. You would use <code>async</code>/<code>await</code> to perform tasks, where you must wait for the response.</p><p>In Flutter, use the asynchronous facilities that the Dart language provides, also named <code>async</code>/<code>await</code>, to perform asynchronous work. This is very similar to C# and should be very easy to use for any Xamarin.Forms developer.</p><p>For example, you can run network code without causing the UI to hang by using <code>async</code>/<code>await</code> and letting Dart do the heavy lifting:</p> <?code-excerpt "lib/data.dart (load-data)"?> <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:#0468D7">Future</span><span style="color:#222222"><</span><span style="color:#BD2314">void</span><span style="color:#222222">> </span><span style="color:#6200EE">loadData</span><span style="color:#222222">() </span><span style="color:#BD2314">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> Uri</span><span style="color:#222222"> dataURL = </span><span style="color:#0468D7">Uri</span><span style="color:#222222">.</span><span style="color:#6200EE">parse</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#0C7064"> 'https://jsonplaceholder.typicode.com/posts'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> );</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#222222"> http.</span><span style="color:#0468D7">Response</span><span style="color:#222222"> response = </span><span style="color:#BD2314">await</span><span style="color:#222222"> http.</span><span style="color:#6200EE">get</span><span style="color:#222222">(dataURL);</span></span> <span class="line"><span style="color:#6200EE"> setState</span><span style="color:#222222">(() {</span></span> <span class="line"><span style="color:#222222"> data = </span><span style="color:#6200EE">jsonDecode</span><span style="color:#222222">(response.body);</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>Once the awaited network call is done, update the UI by calling <code>setState()</code>, which triggers a rebuild of the widget subtree and updates the data.</p><p>The following example loads data asynchronously and displays it in a <code>ListView</code>:</p> <?code-excerpt "lib/data.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"> 'dart:convert'</span><span style="color:#222222">;</span></span> <span class="line"></span> <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 style="color:#BD2314">import</span><span style="color:#0C7064"> 'package:http/http.dart'</span><span style="color:#BD2314"> as</span><span style="color:#222222"> http;</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314">void</span><span style="color:#6200EE"> main</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#6200EE"> runApp</span><span style="color:#222222">(</span><span style="color:#BD2314">const</span><span style="color:#0468D7"> SampleApp</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"> SampleApp</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"> SampleApp</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:#BD2314"> const</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">'Sample App'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> home: </span><span style="color:#0468D7">SampleAppPage</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> <span class="line"><span style="color:#BD2314">class</span><span style="color:#0468D7"> SampleAppPage</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"> SampleAppPage</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">SampleAppPage</span><span style="color:#222222">> </span><span style="color:#6200EE">createState</span><span style="color:#222222">() => </span><span style="color:#0468D7">_SampleAppPageState</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"> _SampleAppPageState</span><span style="color:#BD2314"> extends</span><span style="color:#0468D7"> State</span><span style="color:#222222"><</span><span style="color:#0468D7">SampleAppPage</span><span style="color:#222222">> {</span></span> <span class="line"><span style="color:#0468D7"> List</span><span style="color:#222222"><</span><span style="color:#0468D7">Map</span><span style="color:#222222"><</span><span style="color:#0468D7">String</span><span style="color:#222222">, </span><span style="color:#0468D7">dynamic</span><span style="color:#222222">>> data = <</span><span style="color:#0468D7">Map</span><span style="color:#222222"><</span><span style="color:#0468D7">String</span><span style="color:#222222">, </span><span style="color:#0468D7">dynamic</span><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:#BD2314"> void</span><span style="color:#6200EE"> initState</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#BD2314"> super</span><span style="color:#222222">.</span><span style="color:#6200EE">initState</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#6200EE"> loadData</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:#0468D7"> Future</span><span style="color:#222222"><</span><span style="color:#BD2314">void</span><span style="color:#222222">> </span><span style="color:#6200EE">loadData</span><span style="color:#222222">() </span><span style="color:#BD2314">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> Uri</span><span style="color:#222222"> dataURL = </span><span style="color:#0468D7">Uri</span><span style="color:#222222">.</span><span style="color:#6200EE">parse</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#0C7064"> 'https://jsonplaceholder.typicode.com/posts'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> );</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#222222"> http.</span><span style="color:#0468D7">Response</span><span style="color:#222222"> response = </span><span style="color:#BD2314">await</span><span style="color:#222222"> http.</span><span style="color:#6200EE">get</span><span style="color:#222222">(dataURL);</span></span> <span class="line"><span style="color:#6200EE"> setState</span><span style="color:#222222">(() {</span></span> <span class="line"><span style="color:#222222"> data = </span><span style="color:#6200EE">jsonDecode</span><span style="color:#222222">(response.body);</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:#0468D7"> Widget</span><span style="color:#6200EE"> getRow</span><span style="color:#222222">(</span><span style="color:#0468D7">int</span><span style="color:#222222"> index) {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#0468D7"> Padding</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">10</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 style="color:#0C7064">'Row </span><span style="color:#0C7064">${</span><span style="color:#222222">data</span><span style="color:#0C7064">[</span><span style="color:#222222">index</span><span style="color:#0C7064">][</span><span style="color:#0C7064">'title'</span><span style="color:#0C7064">]}</span><span style="color:#0C7064">'</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"> @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"> 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">(title: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'Sample App'</span><span style="color:#222222">)),</span></span> <span class="line"><span style="color:#222222"> body: </span><span style="color:#0468D7">ListView</span><span style="color:#222222">.</span><span style="color:#6200EE">builder</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> itemCount: data.length,</span></span> <span class="line"><span style="color:#222222"> itemBuilder: (context, index) {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#6200EE"> getRow</span><span style="color:#222222">(index);</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>Refer to the next section for more information on doing work in the background, and how Flutter differs from Android.</p><div class="header-wrapper"><h3 id="how-do-you-move-work-to-a-background-thread">How do you move work to a background thread?</h3><a class="heading-link" href="#how-do-you-move-work-to-a-background-thread" aria-label="Link to 'How do you move work to a background thread?' section">#</a></div><p>Since Flutter is single threaded and runs an event loop, you don't have to worry about thread management or spawning background threads. This is very similar to Xamarin.Forms. If you're doing I/O-bound work, such as disk access or a network call, then you can safely use <code>async</code>/<code>await</code> and you're all set.</p><p>If, on the other hand, you need to do computationally intensive work that keeps the CPU busy, you want to move it to an <code>Isolate</code> to avoid blocking the event loop, like you would keep <em>any</em> sort of work out of the main thread. This is similar to when you move things to a different thread via <code>Task.Run()</code> in Xamarin.Forms.</p><p>For I/O-bound work, declare the function as an <code>async</code> function, and <code>await</code> on long-running tasks inside the function:</p> <?code-excerpt "lib/data.dart (load-data)"?> <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:#0468D7">Future</span><span style="color:#222222"><</span><span style="color:#BD2314">void</span><span style="color:#222222">> </span><span style="color:#6200EE">loadData</span><span style="color:#222222">() </span><span style="color:#BD2314">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> Uri</span><span style="color:#222222"> dataURL = </span><span style="color:#0468D7">Uri</span><span style="color:#222222">.</span><span style="color:#6200EE">parse</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#0C7064"> 'https://jsonplaceholder.typicode.com/posts'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> );</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#222222"> http.</span><span style="color:#0468D7">Response</span><span style="color:#222222"> response = </span><span style="color:#BD2314">await</span><span style="color:#222222"> http.</span><span style="color:#6200EE">get</span><span style="color:#222222">(dataURL);</span></span> <span class="line"><span style="color:#6200EE"> setState</span><span style="color:#222222">(() {</span></span> <span class="line"><span style="color:#222222"> data = </span><span style="color:#6200EE">jsonDecode</span><span style="color:#222222">(response.body);</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>This is how you would typically do network or database calls, which are both I/O operations.</p><p>However, there are times when you might be processing a large amount of data and your UI hangs. In Flutter, use <code>Isolate</code>s to take advantage of multiple CPU cores to do long-running or computationally intensive tasks.</p><p>Isolates are separate execution threads that do not share any memory with the main execution memory heap. This is a difference between <code>Task.Run()</code>. This means you can't access variables from the main thread, or update your UI by calling <code>setState()</code>.</p><p>The following example shows, in a simple isolate, how to share data back to the main thread to update the UI.</p> <?code-excerpt "lib/isolates.dart (simple-isolate)"?> <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:#0468D7">Future</span><span style="color:#222222"><</span><span style="color:#BD2314">void</span><span style="color:#222222">> </span><span style="color:#6200EE">loadData</span><span style="color:#222222">() </span><span style="color:#BD2314">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> ReceivePort</span><span style="color:#222222"> receivePort = </span><span style="color:#0468D7">ReceivePort</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#BD2314"> await</span><span style="color:#0468D7"> Isolate</span><span style="color:#222222">.</span><span style="color:#6200EE">spawn</span><span style="color:#222222">(dataLoader, receivePort.sendPort);</span></span> <span class="line"></span> <span class="line"><span style="color:#6E6E70"> // The 'echo' isolate sends its SendPort as the first message</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> SendPort</span><span style="color:#222222"> sendPort = </span><span style="color:#BD2314">await</span><span style="color:#222222"> receivePort.first </span><span style="color:#BD2314">as</span><span style="color:#0468D7"> SendPort</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> List</span><span style="color:#222222"><</span><span style="color:#0468D7">Map</span><span style="color:#222222"><</span><span style="color:#0468D7">String</span><span style="color:#222222">, </span><span style="color:#0468D7">dynamic</span><span style="color:#222222">>> msg = </span><span style="color:#BD2314">await</span><span style="color:#6200EE"> sendReceive</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> sendPort,</span></span> <span class="line"><span style="color:#0C7064"> 'https://jsonplaceholder.typicode.com/posts'</span><span style="color:#222222">,</span></span> <span class="line"><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"> data = msg;</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">// The entry point for the isolate</span></span> <span class="line"><span style="color:#BD2314">static</span><span style="color:#0468D7"> Future</span><span style="color:#222222"><</span><span style="color:#BD2314">void</span><span style="color:#222222">> </span><span style="color:#6200EE">dataLoader</span><span style="color:#222222">(</span><span style="color:#0468D7">SendPort</span><span style="color:#222222"> sendPort) </span><span style="color:#BD2314">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#6E6E70"> // Open the ReceivePort for incoming messages.</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> ReceivePort</span><span style="color:#222222"> port = </span><span style="color:#0468D7">ReceivePort</span><span style="color:#222222">();</span></span> <span class="line"></span> <span class="line"><span style="color:#6E6E70"> // Notify any other isolates what port this isolate listens to.</span></span> <span class="line"><span style="color:#222222"> sendPort.</span><span style="color:#6200EE">send</span><span style="color:#222222">(port.sendPort);</span></span> <span class="line"><span style="color:#BD2314"> await</span><span style="color:#BD2314"> for</span><span style="color:#222222"> (</span><span style="color:#BD2314">final</span><span style="color:#0468D7"> dynamic</span><span style="color:#222222"> msg </span><span style="color:#BD2314">in</span><span style="color:#222222"> port) {</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> String</span><span style="color:#222222"> url = msg[</span><span style="color:#0C7064">0</span><span style="color:#222222">] </span><span style="color:#BD2314">as</span><span style="color:#0468D7"> String</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> SendPort</span><span style="color:#222222"> replyTo = msg[</span><span style="color:#0C7064">1</span><span style="color:#222222">] </span><span style="color:#BD2314">as</span><span style="color:#0468D7"> SendPort</span><span style="color:#222222">;</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> Uri</span><span style="color:#222222"> dataURL = </span><span style="color:#0468D7">Uri</span><span style="color:#222222">.</span><span style="color:#6200EE">parse</span><span style="color:#222222">(url);</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#222222"> http.</span><span style="color:#0468D7">Response</span><span style="color:#222222"> response = </span><span style="color:#BD2314">await</span><span style="color:#222222"> http.</span><span style="color:#6200EE">get</span><span style="color:#222222">(dataURL);</span></span> <span class="line"><span style="color:#6E6E70"> // Lots of JSON to parse</span></span> <span class="line"><span style="color:#222222"> replyTo.</span><span style="color:#6200EE">send</span><span style="color:#222222">(</span><span style="color:#6200EE">jsonDecode</span><span style="color:#222222">(response.body) </span><span style="color:#BD2314">as</span><span style="color:#0468D7"> List</span><span style="color:#222222"><</span><span style="color:#0468D7">Map</span><span style="color:#222222"><</span><span style="color:#0468D7">String</span><span style="color:#222222">, </span><span style="color:#0468D7">dynamic</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:#0468D7">Future</span><span style="color:#222222"><</span><span style="color:#0468D7">List</span><span style="color:#222222"><</span><span style="color:#0468D7">Map</span><span style="color:#222222"><</span><span style="color:#0468D7">String</span><span style="color:#222222">, </span><span style="color:#0468D7">dynamic</span><span style="color:#222222">>>> </span><span style="color:#6200EE">sendReceive</span><span style="color:#222222">(</span><span style="color:#0468D7">SendPort</span><span style="color:#222222"> port, </span><span style="color:#0468D7">String</span><span style="color:#222222"> msg) {</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> ReceivePort</span><span style="color:#222222"> response = </span><span style="color:#0468D7">ReceivePort</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#222222"> port.</span><span style="color:#6200EE">send</span><span style="color:#222222">(<</span><span style="color:#0468D7">dynamic</span><span style="color:#222222">>[msg, response.sendPort]);</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#222222"> response.first </span><span style="color:#BD2314">as</span><span style="color:#0468D7"> Future</span><span style="color:#222222"><</span><span style="color:#0468D7">List</span><span style="color:#222222"><</span><span style="color:#0468D7">Map</span><span style="color:#222222"><</span><span style="color:#0468D7">String</span><span style="color:#222222">, </span><span style="color:#0468D7">dynamic</span><span style="color:#222222">>>>;</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><p>Here, <code>dataLoader()</code> is the <code>Isolate</code> that runs in its own separate execution thread. In the isolate, you can perform more CPU intensive processing (parsing a big JSON, for example), or perform computationally intensive math, such as encryption or signal processing.</p><p>You can run the full example below:</p> <?code-excerpt "lib/isolates.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"> 'dart:async'</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#BD2314">import</span><span style="color:#0C7064"> 'dart:convert'</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#BD2314">import</span><span style="color:#0C7064"> 'dart:isolate'</span><span style="color:#222222">;</span></span> <span class="line"></span> <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 style="color:#BD2314">import</span><span style="color:#0C7064"> 'package:http/http.dart'</span><span style="color:#BD2314"> as</span><span style="color:#222222"> http;</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314">void</span><span style="color:#6200EE"> main</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#6200EE"> runApp</span><span style="color:#222222">(</span><span style="color:#BD2314">const</span><span style="color:#0468D7"> SampleApp</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"> SampleApp</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"> SampleApp</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:#BD2314"> const</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">'Sample App'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> home: </span><span style="color:#0468D7">SampleAppPage</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> <span class="line"><span style="color:#BD2314">class</span><span style="color:#0468D7"> SampleAppPage</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"> SampleAppPage</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">SampleAppPage</span><span style="color:#222222">> </span><span style="color:#6200EE">createState</span><span style="color:#222222">() => </span><span style="color:#0468D7">_SampleAppPageState</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"> _SampleAppPageState</span><span style="color:#BD2314"> extends</span><span style="color:#0468D7"> State</span><span style="color:#222222"><</span><span style="color:#0468D7">SampleAppPage</span><span style="color:#222222">> {</span></span> <span class="line"><span style="color:#0468D7"> List</span><span style="color:#222222"><</span><span style="color:#0468D7">Map</span><span style="color:#222222"><</span><span style="color:#0468D7">String</span><span style="color:#222222">, </span><span style="color:#0468D7">dynamic</span><span style="color:#222222">>> data = <</span><span style="color:#0468D7">Map</span><span style="color:#222222"><</span><span style="color:#0468D7">String</span><span style="color:#222222">, </span><span style="color:#0468D7">dynamic</span><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:#BD2314"> void</span><span style="color:#6200EE"> initState</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#BD2314"> super</span><span style="color:#222222">.</span><span style="color:#6200EE">initState</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#6200EE"> loadData</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:#0468D7"> bool</span><span style="color:#BD2314"> get</span><span style="color:#222222"> showLoadingDialog => data.isEmpty;</span></span> <span class="line"></span> <span class="line"><span style="color:#0468D7"> Future</span><span style="color:#222222"><</span><span style="color:#BD2314">void</span><span style="color:#222222">> </span><span style="color:#6200EE">loadData</span><span style="color:#222222">() </span><span style="color:#BD2314">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> ReceivePort</span><span style="color:#222222"> receivePort = </span><span style="color:#0468D7">ReceivePort</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#BD2314"> await</span><span style="color:#0468D7"> Isolate</span><span style="color:#222222">.</span><span style="color:#6200EE">spawn</span><span style="color:#222222">(dataLoader, receivePort.sendPort);</span></span> <span class="line"></span> <span class="line"><span style="color:#6E6E70"> // The 'echo' isolate sends its SendPort as the first message</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> SendPort</span><span style="color:#222222"> sendPort = </span><span style="color:#BD2314">await</span><span style="color:#222222"> receivePort.first </span><span style="color:#BD2314">as</span><span style="color:#0468D7"> SendPort</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> List</span><span style="color:#222222"><</span><span style="color:#0468D7">Map</span><span style="color:#222222"><</span><span style="color:#0468D7">String</span><span style="color:#222222">, </span><span style="color:#0468D7">dynamic</span><span style="color:#222222">>> msg = </span><span style="color:#BD2314">await</span><span style="color:#6200EE"> sendReceive</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> sendPort,</span></span> <span class="line"><span style="color:#0C7064"> 'https://jsonplaceholder.typicode.com/posts'</span><span style="color:#222222">,</span></span> <span class="line"><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"> data = msg;</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"> // The entry point for the isolate</span></span> <span class="line"><span style="color:#BD2314"> static</span><span style="color:#0468D7"> Future</span><span style="color:#222222"><</span><span style="color:#BD2314">void</span><span style="color:#222222">> </span><span style="color:#6200EE">dataLoader</span><span style="color:#222222">(</span><span style="color:#0468D7">SendPort</span><span style="color:#222222"> sendPort) </span><span style="color:#BD2314">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#6E6E70"> // Open the ReceivePort for incoming messages.</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> ReceivePort</span><span style="color:#222222"> port = </span><span style="color:#0468D7">ReceivePort</span><span style="color:#222222">();</span></span> <span class="line"></span> <span class="line"><span style="color:#6E6E70"> // Notify any other isolates what port this isolate listens to.</span></span> <span class="line"><span style="color:#222222"> sendPort.</span><span style="color:#6200EE">send</span><span style="color:#222222">(port.sendPort);</span></span> <span class="line"><span style="color:#BD2314"> await</span><span style="color:#BD2314"> for</span><span style="color:#222222"> (</span><span style="color:#BD2314">final</span><span style="color:#0468D7"> dynamic</span><span style="color:#222222"> msg </span><span style="color:#BD2314">in</span><span style="color:#222222"> port) {</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> String</span><span style="color:#222222"> url = msg[</span><span style="color:#0C7064">0</span><span style="color:#222222">] </span><span style="color:#BD2314">as</span><span style="color:#0468D7"> String</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> SendPort</span><span style="color:#222222"> replyTo = msg[</span><span style="color:#0C7064">1</span><span style="color:#222222">] </span><span style="color:#BD2314">as</span><span style="color:#0468D7"> SendPort</span><span style="color:#222222">;</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> Uri</span><span style="color:#222222"> dataURL = </span><span style="color:#0468D7">Uri</span><span style="color:#222222">.</span><span style="color:#6200EE">parse</span><span style="color:#222222">(url);</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#222222"> http.</span><span style="color:#0468D7">Response</span><span style="color:#222222"> response = </span><span style="color:#BD2314">await</span><span style="color:#222222"> http.</span><span style="color:#6200EE">get</span><span style="color:#222222">(dataURL);</span></span> <span class="line"><span style="color:#6E6E70"> // Lots of JSON to parse</span></span> <span class="line"><span style="color:#222222"> replyTo.</span><span style="color:#6200EE">send</span><span style="color:#222222">(</span><span style="color:#6200EE">jsonDecode</span><span style="color:#222222">(response.body) </span><span style="color:#BD2314">as</span><span style="color:#0468D7"> List</span><span style="color:#222222"><</span><span style="color:#0468D7">Map</span><span style="color:#222222"><</span><span style="color:#0468D7">String</span><span style="color:#222222">, </span><span style="color:#0468D7">dynamic</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:#0468D7"> Future</span><span style="color:#222222"><</span><span style="color:#0468D7">List</span><span style="color:#222222"><</span><span style="color:#0468D7">Map</span><span style="color:#222222"><</span><span style="color:#0468D7">String</span><span style="color:#222222">, </span><span style="color:#0468D7">dynamic</span><span style="color:#222222">>>> </span><span style="color:#6200EE">sendReceive</span><span style="color:#222222">(</span><span style="color:#0468D7">SendPort</span><span style="color:#222222"> port, </span><span style="color:#0468D7">String</span><span style="color:#222222"> msg) {</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> ReceivePort</span><span style="color:#222222"> response = </span><span style="color:#0468D7">ReceivePort</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#222222"> port.</span><span style="color:#6200EE">send</span><span style="color:#222222">(<</span><span style="color:#0468D7">dynamic</span><span style="color:#222222">>[msg, response.sendPort]);</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#222222"> response.first </span><span style="color:#BD2314">as</span><span style="color:#0468D7"> Future</span><span style="color:#222222"><</span><span style="color:#0468D7">List</span><span style="color:#222222"><</span><span style="color:#0468D7">Map</span><span style="color:#222222"><</span><span style="color:#0468D7">String</span><span style="color:#222222">, </span><span style="color:#0468D7">dynamic</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:#0468D7"> Widget</span><span style="color:#6200EE"> getBody</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#BD2314"> if</span><span style="color:#222222"> (showLoadingDialog) {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#6200EE"> getProgressDialog</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#6200EE"> getListView</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:#0468D7"> Widget</span><span style="color:#6200EE"> getProgressDialog</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#BD2314"> const</span><span style="color:#0468D7"> Center</span><span style="color:#222222">(child: </span><span style="color:#0468D7">CircularProgressIndicator</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:#0468D7"> ListView</span><span style="color:#6200EE"> getListView</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#0468D7"> ListView</span><span style="color:#222222">.</span><span style="color:#6200EE">builder</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> itemCount: data.length,</span></span> <span class="line"><span style="color:#222222"> itemBuilder: (context, index) {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#6200EE"> getRow</span><span style="color:#222222">(index);</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:#0468D7"> Widget</span><span style="color:#6200EE"> getRow</span><span style="color:#222222">(</span><span style="color:#0468D7">int</span><span style="color:#222222"> index) {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#0468D7"> Padding</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">10</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 style="color:#0C7064">'Row </span><span style="color:#0C7064">${</span><span style="color:#222222">data</span><span style="color:#0C7064">[</span><span style="color:#222222">index</span><span style="color:#0C7064">][</span><span style="color:#0C7064">'title'</span><span style="color:#0C7064">]}</span><span style="color:#0C7064">'</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"> @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"> 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">(title: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'Sample App'</span><span style="color:#222222">)),</span></span> <span class="line"><span style="color:#222222"> body: </span><span style="color:#6200EE">getBody</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><div class="header-wrapper"><h3 id="how-do-i-make-network-requests">How do I make network requests?</h3><a class="heading-link" href="#how-do-i-make-network-requests" aria-label="Link to 'How do I make network requests?' section">#</a></div><p>In Xamarin.Forms you would use <code>HttpClient</code>. Making a network call in Flutter is easy when you use the popular <a href="https://pub.dev/packages/http"><code>http</code> package</a>. This abstracts away a lot of the networking that you might normally implement yourself, making it simple to make network calls.</p><p>To use the <code>http</code> package, add it to your dependencies in <code>pubspec.yaml</code>:</p><div class="code-block-wrapper language-yaml"><div class="code-block-body"><span class="code-block-language" title="Language yaml">yaml</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#0468D7">dependencies</span><span style="color:#222222">:</span></span> <span class="line"><span style="color:#0468D7"> http</span><span style="color:#222222">: </span><span style="color:#0C7064">^1.1.0</span></span></code></pre></div></div><p>To make a network request, call <code>await</code> on the <code>async</code> function <code>http.get()</code>:</p> <?code-excerpt "lib/data.dart (load-data)"?> <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:#0468D7">Future</span><span style="color:#222222"><</span><span style="color:#BD2314">void</span><span style="color:#222222">> </span><span style="color:#6200EE">loadData</span><span style="color:#222222">() </span><span style="color:#BD2314">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> Uri</span><span style="color:#222222"> dataURL = </span><span style="color:#0468D7">Uri</span><span style="color:#222222">.</span><span style="color:#6200EE">parse</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#0C7064"> 'https://jsonplaceholder.typicode.com/posts'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> );</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#222222"> http.</span><span style="color:#0468D7">Response</span><span style="color:#222222"> response = </span><span style="color:#BD2314">await</span><span style="color:#222222"> http.</span><span style="color:#6200EE">get</span><span style="color:#222222">(dataURL);</span></span> <span class="line"><span style="color:#6200EE"> setState</span><span style="color:#222222">(() {</span></span> <span class="line"><span style="color:#222222"> data = </span><span style="color:#6200EE">jsonDecode</span><span style="color:#222222">(response.body);</span></span> <span class="line"><span style="color:#222222"> });</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><div class="header-wrapper"><h3 id="how-do-i-show-the-progress-for-a-long-running-task">How do I show the progress for a long-running task?</h3><a class="heading-link" href="#how-do-i-show-the-progress-for-a-long-running-task" aria-label="Link to 'How do I show the progress for a long-running task?' section">#</a></div><p>In Xamarin.Forms you would typically create a loading indicator, either directly in XAML or through a 3rd party plugin such as AcrDialogs.</p><p>In Flutter, use a <code>ProgressIndicator</code> widget. Show the progress programmatically by controlling when it's rendered through a boolean flag. Tell Flutter to update its state before your long-running task starts, and hide it after it ends.</p><p>In the example below, the build function is separated into three different functions. If <code>showLoadingDialog</code> is <code>true</code> (when <code>widgets.length == 0</code>), then render the <code>ProgressIndicator</code>. Otherwise, render the <code>ListView</code> with the data returned from a network call.</p> <?code-excerpt "lib/loading.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"> 'dart:async'</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#BD2314">import</span><span style="color:#0C7064"> 'dart:convert'</span><span style="color:#222222">;</span></span> <span class="line"></span> <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 style="color:#BD2314">import</span><span style="color:#0C7064"> 'package:http/http.dart'</span><span style="color:#BD2314"> as</span><span style="color:#222222"> http;</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314">void</span><span style="color:#6200EE"> main</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#6200EE"> runApp</span><span style="color:#222222">(</span><span style="color:#BD2314">const</span><span style="color:#0468D7"> SampleApp</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"> SampleApp</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"> SampleApp</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:#BD2314"> const</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">'Sample App'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> home: </span><span style="color:#0468D7">SampleAppPage</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> <span class="line"><span style="color:#BD2314">class</span><span style="color:#0468D7"> SampleAppPage</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"> SampleAppPage</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">SampleAppPage</span><span style="color:#222222">> </span><span style="color:#6200EE">createState</span><span style="color:#222222">() => </span><span style="color:#0468D7">_SampleAppPageState</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"> _SampleAppPageState</span><span style="color:#BD2314"> extends</span><span style="color:#0468D7"> State</span><span style="color:#222222"><</span><span style="color:#0468D7">SampleAppPage</span><span style="color:#222222">> {</span></span> <span class="line"><span style="color:#0468D7"> List</span><span style="color:#222222"><</span><span style="color:#0468D7">Map</span><span style="color:#222222"><</span><span style="color:#0468D7">String</span><span style="color:#222222">, </span><span style="color:#0468D7">dynamic</span><span style="color:#222222">>> data = <</span><span style="color:#0468D7">Map</span><span style="color:#222222"><</span><span style="color:#0468D7">String</span><span style="color:#222222">, </span><span style="color:#0468D7">dynamic</span><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:#BD2314"> void</span><span style="color:#6200EE"> initState</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#BD2314"> super</span><span style="color:#222222">.</span><span style="color:#6200EE">initState</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#6200EE"> loadData</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:#0468D7"> bool</span><span style="color:#BD2314"> get</span><span style="color:#222222"> showLoadingDialog => data.isEmpty;</span></span> <span class="line"></span> <span class="line"><span style="color:#0468D7"> Future</span><span style="color:#222222"><</span><span style="color:#BD2314">void</span><span style="color:#222222">> </span><span style="color:#6200EE">loadData</span><span style="color:#222222">() </span><span style="color:#BD2314">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> Uri</span><span style="color:#222222"> dataURL = </span><span style="color:#0468D7">Uri</span><span style="color:#222222">.</span><span style="color:#6200EE">parse</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#0C7064"> 'https://jsonplaceholder.typicode.com/posts'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> );</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#222222"> http.</span><span style="color:#0468D7">Response</span><span style="color:#222222"> response = </span><span style="color:#BD2314">await</span><span style="color:#222222"> http.</span><span style="color:#6200EE">get</span><span style="color:#222222">(dataURL);</span></span> <span class="line"><span style="color:#6200EE"> setState</span><span style="color:#222222">(() {</span></span> <span class="line"><span style="color:#222222"> data = </span><span style="color:#6200EE">jsonDecode</span><span style="color:#222222">(response.body);</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:#0468D7"> Widget</span><span style="color:#6200EE"> getBody</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#BD2314"> if</span><span style="color:#222222"> (showLoadingDialog) {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#6200EE"> getProgressDialog</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#6200EE"> getListView</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:#0468D7"> Widget</span><span style="color:#6200EE"> getProgressDialog</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#BD2314"> const</span><span style="color:#0468D7"> Center</span><span style="color:#222222">(child: </span><span style="color:#0468D7">CircularProgressIndicator</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:#0468D7"> ListView</span><span style="color:#6200EE"> getListView</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#0468D7"> ListView</span><span style="color:#222222">.</span><span style="color:#6200EE">builder</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> itemCount: data.length,</span></span> <span class="line"><span style="color:#222222"> itemBuilder: (context, index) {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#6200EE"> getRow</span><span style="color:#222222">(index);</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:#0468D7"> Widget</span><span style="color:#6200EE"> getRow</span><span style="color:#222222">(</span><span style="color:#0468D7">int</span><span style="color:#222222"> index) {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#0468D7"> Padding</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">10</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 style="color:#0C7064">'Row </span><span style="color:#0C7064">${</span><span style="color:#222222">data</span><span style="color:#0C7064">[</span><span style="color:#222222">index</span><span style="color:#0C7064">][</span><span style="color:#0C7064">'title'</span><span style="color:#0C7064">]}</span><span style="color:#0C7064">'</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"> @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"> 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">(title: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'Sample App'</span><span style="color:#222222">)),</span></span> <span class="line"><span style="color:#222222"> body: </span><span style="color:#6200EE">getBody</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><div class="header-wrapper"><h2 id="project-structure-resources">Project structure & resources</h2><a class="heading-link" href="#project-structure-resources" aria-label="Link to 'Project structure & resources' section">#</a></div><div class="header-wrapper"><h3 id="where-do-i-store-my-image-files">Where do I store my image files?</h3><a class="heading-link" href="#where-do-i-store-my-image-files" aria-label="Link to 'Where do I store my image files?' section">#</a></div><p>Xamarin.Forms has no platform independent way of storing images, you had to place images in the iOS <code>xcasset</code> folder, or on Android in the various <code>drawable</code> folders.</p><p>While Android and iOS treat resources and assets as distinct items, Flutter apps have only assets. All resources that would live in the <code>Resources/drawable-*</code> folders on Android, are placed in an assets' folder for Flutter.</p><p>Flutter follows a simple density-based format like iOS. Assets might be <code>1.0x</code>, <code>2.0x</code>, <code>3.0x</code>, or any other multiplier. Flutter doesn't have <code>dp</code>s but there are logical pixels, which are basically the same as device-independent pixels. Flutter's <a href="https://api.flutter.dev/flutter/dart-ui/FlutterView/devicePixelRatio.html"><code>devicePixelRatio</code></a> expresses the ratio of physical pixels in a single logical pixel.</p><p>The equivalent to Android's density buckets are:</p><div class="table-wrapper"><table><thead><tr><th>Android density qualifier</th><th>Flutter pixel ratio</th></tr></thead><tbody><tr><td><code>ldpi</code></td><td><code>0.75x</code></td></tr><tr><td><code>mdpi</code></td><td><code>1.0x</code></td></tr><tr><td><code>hdpi</code></td><td><code>1.5x</code></td></tr><tr><td><code>xhdpi</code></td><td><code>2.0x</code></td></tr><tr><td><code>xxhdpi</code></td><td><code>3.0x</code></td></tr><tr><td><code>xxxhdpi</code></td><td><code>4.0x</code></td></tr></tbody></table></div><p>Assets are located in any arbitrary folder— Flutter has no predefined folder structure. You declare the assets (with location) in the <code>pubspec.yaml</code> file, and Flutter picks them up.</p><p>To add a new image asset called <code>my_icon.png</code> to our Flutter project, for example, and deciding that it should live in a folder we arbitrarily called <code>images</code>, you would put the base image (1.0x) in the <code>images</code> folder, and all the other variants in sub-folders called with the appropriate ratio multiplier:</p><div class="code-block-wrapper language-plaintext"><div class="code-block-body"><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span>images/my_icon.png // Base: 1.0x image</span></span> <span class="line"><span>images/2.0x/my_icon.png // 2.0x image</span></span> <span class="line"><span>images/3.0x/my_icon.png // 3.0x image</span></span></code></pre></div></div><p>Next, you'll need to declare these images in your <code>pubspec.yaml</code> file:</p><div class="code-block-wrapper language-yaml"><div class="code-block-body"><span class="code-block-language" title="Language yaml">yaml</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#0468D7">assets</span><span style="color:#222222">:</span></span> <span class="line"><span style="color:#222222"> - </span><span style="color:#0C7064">images/my_icon.jpeg</span></span></code></pre></div></div><p>You can directly access your images in an <code>Image.asset</code> widget:</p> <?code-excerpt "lib/images.dart (image-asset)"?> <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">@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"> Image</span><span style="color:#222222">.</span><span style="color:#6200EE">asset</span><span style="color:#222222">(</span><span style="color:#0C7064">'images/my_icon.png'</span><span style="color:#222222">);</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><p>or using <code>AssetImage</code>:</p> <?code-excerpt "lib/images.dart (asset-image)"?> <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">@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:#BD2314"> const</span><span style="color:#0468D7"> Image</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> image: </span><span style="color:#0468D7">AssetImage</span><span style="color:#222222">(</span><span style="color:#0C7064">'images/my_image.png'</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>More detailed information can be found in <a href="/ui/assets/assets-and-images">Adding assets and images</a>.</p><div class="header-wrapper"><h3 id="where-do-i-store-strings-how-do-i-handle-localization">Where do I store strings? How do I handle localization?</h3><a class="heading-link" href="#where-do-i-store-strings-how-do-i-handle-localization" aria-label="Link to 'Where do I store strings? How do I handle localization?' section">#</a></div><p>Unlike .NET which has <code>resx</code> files, Flutter doesn't currently have a dedicated system for handling strings. At the moment, the best practice is to declare your copy text in a class as static fields and access them from there. For example:</p> <?code-excerpt "lib/strings.dart (strings-class)"?> <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"> Strings</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#BD2314"> static</span><span style="color:#BD2314"> const</span><span style="color:#0468D7"> String</span><span style="color:#222222"> welcomeMessage = </span><span style="color:#0C7064">'Welcome To Flutter'</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><p>You can access your strings as such:</p> <?code-excerpt "lib/strings.dart (access-string)" replace="/return const //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:#0468D7">Text</span><span style="color:#222222">(</span><span style="color:#0468D7">Strings</span><span style="color:#222222">.welcomeMessage);</span></span></code></pre></div></div><p>By default, Flutter only supports US English for its strings. If you need to add support for other languages, include the <code>flutter_localizations</code> package. You might also need to add Dart's <a href="https://pub.dev/packages/intl"><code>intl</code></a> package to use i10n machinery, such as date/time formatting.</p><div class="code-block-wrapper language-yaml"><div class="code-block-body"><span class="code-block-language" title="Language yaml">yaml</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#0468D7">dependencies</span><span style="color:#222222">:</span></span> <span class="line"><span style="color:#0468D7"> flutter_localizations</span><span style="color:#222222">:</span></span> <span class="line"><span style="color:#0468D7"> sdk</span><span style="color:#222222">: </span><span style="color:#0C7064">flutter</span></span> <span class="line"><span style="color:#0468D7"> intl</span><span style="color:#222222">: </span><span style="color:#0C7064">any</span><span style="color:#6E6E70"> # Use version of intl from flutter_localizations.</span></span></code></pre></div></div><p>To use the <code>flutter_localizations</code> package, specify the <code>localizationsDelegates</code> and <code>supportedLocales</code> on the app widget:</p> <?code-excerpt "lib/strings.dart (localization)"?> <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_localizations/flutter_localizations.dart'</span><span style="color:#222222">;</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314">class</span><span style="color:#0468D7"> MyWidget</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"> MyWidget</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:#BD2314"> const</span><span style="color:#0468D7"> MaterialApp</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> localizationsDelegates: <</span><span style="color:#0468D7">LocalizationsDelegate</span><span style="color:#222222"><</span><span style="color:#0468D7">dynamic</span><span style="color:#222222">>>[</span></span> <span class="line"><span style="color:#6E6E70"> // Add app-specific localization delegate[s] here</span></span> <span class="line"><span style="color:#0468D7"> GlobalMaterialLocalizations</span><span style="color:#222222">.delegate,</span></span> <span class="line"><span style="color:#0468D7"> GlobalWidgetsLocalizations</span><span style="color:#222222">.delegate,</span></span> <span class="line"><span style="color:#222222"> ],</span></span> <span class="line"><span style="color:#222222"> supportedLocales: <</span><span style="color:#0468D7">Locale</span><span style="color:#222222">>[</span></span> <span class="line"><span style="color:#0468D7"> Locale</span><span style="color:#222222">(</span><span style="color:#0C7064">'en'</span><span style="color:#222222">, </span><span style="color:#0C7064">'US'</span><span style="color:#222222">), </span><span style="color:#6E6E70">// English</span></span> <span class="line"><span style="color:#0468D7"> Locale</span><span style="color:#222222">(</span><span style="color:#0C7064">'he'</span><span style="color:#222222">, </span><span style="color:#0C7064">'IL'</span><span style="color:#222222">), </span><span style="color:#6E6E70">// Hebrew</span></span> <span class="line"><span style="color:#6E6E70"> // ... other locales the app supports</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>The delegates contain the actual localized values, while the <code>supportedLocales</code> defines which locales the app supports. The above example uses a <code>MaterialApp</code>, so it has both a <code>GlobalWidgetsLocalizations</code> for the base widgets localized values, and a <code>MaterialWidgetsLocalizations</code> for the Material widgets localizations. If you use <code>WidgetsApp</code> for your app, you don't need the latter. Note that these two delegates contain "default" values, but you'll need to provide one or more delegates for your own app's localizable copy, if you want those to be localized too.</p><p>When initialized, the <code>WidgetsApp</code> (or <code>MaterialApp</code>) creates a <a href="https://api.flutter.dev/flutter/widgets/Localizations-class.html"><code>Localizations</code></a> widget for you, with the delegates you specify. The current locale for the device is always accessible from the <code>Localizations</code> widget from the current context (in the form of a <code>Locale</code> object), or using the <a href="https://api.flutter.dev/flutter/dart-ui/Window/locale.html"><code>Window.locale</code></a>.</p><p>To access localized resources, use the <code>Localizations.of()</code> method to access a specific localizations class that is provided by a given delegate. Use the <a href="https://pub.dev/packages/intl_translation"><code>intl_translation</code></a> package to extract translatable copy to <a href="https://github.com/google/app-resource-bundle">arb</a> files for translating, and importing them back into the app for using them with <code>intl</code>.</p><p>For further details on internationalization and localization in Flutter, see the <a href="/ui/accessibility-and-internationalization/internationalization">internationalization guide</a>, which has sample code with and without the <code>intl</code> package.</p><div class="header-wrapper"><h3 id="where-is-my-project-file">Where is my project file?</h3><a class="heading-link" href="#where-is-my-project-file" aria-label="Link to 'Where is my project file?' section">#</a></div><p>In Xamarin.Forms you will have a <code>csproj</code> file. The closest equivalent in Flutter is pubspec.yaml, which contains package dependencies and various project details. Similar to .NET Standard, files within the same directory are considered part of the project.</p><div class="header-wrapper"><h3 id="what-is-the-equivalent-of-nuget-how-do-i-add-dependencies">What is the equivalent of Nuget? How do I add dependencies?</h3><a class="heading-link" href="#what-is-the-equivalent-of-nuget-how-do-i-add-dependencies" aria-label="Link to 'What is the equivalent of Nuget? How do I add dependencies?' section">#</a></div><p>In the .NET ecosystem, native Xamarin projects and Xamarin.Forms projects had access to Nuget and the built-in package management system. Flutter apps contain a native Android app, native iOS app and Flutter app.</p><p>In Android, you add dependencies by adding to your Gradle build script. In iOS, you add dependencies by adding to your <code>Podfile</code>.</p><p>Flutter uses Dart's own build system, and the Pub package manager. The tools delegate the building of the native Android and iOS wrapper apps to the respective build systems.</p><p>In general, use <code>pubspec.yaml</code> to declare external dependencies to use in Flutter. A good place to find Flutter packages is on <a href="https://pub.dev">pub.dev</a>.</p><div class="header-wrapper"><h2 id="application-lifecycle">Application lifecycle</h2><a class="heading-link" href="#application-lifecycle" aria-label="Link to 'Application lifecycle' section">#</a></div><div class="header-wrapper"><h3 id="how-do-i-listen-to-application-lifecycle-events">How do I listen to application lifecycle events?</h3><a class="heading-link" href="#how-do-i-listen-to-application-lifecycle-events" aria-label="Link to 'How do I listen to application lifecycle events?' section">#</a></div><p>In Xamarin.Forms, you have an <code>Application</code> that contains <code>OnStart</code>, <code>OnResume</code> and <code>OnSleep</code>. In Flutter, you can instead listen to similar lifecycle events by hooking into the <code>WidgetsBinding</code> observer and listening to the <code>didChangeAppLifecycleState()</code> change event.</p><p>The observable lifecycle events are:</p><dl><dt><code>inactive</code></dt><dd>The application is in an inactive state and is not receiving user input. This event is iOS only.</dd><dt><code>paused</code></dt><dd>The application is not currently visible to the user, is not responding to user input, but is running in the background.</dd><dt><code>resumed</code></dt><dd>The application is visible and responding to user input.</dd><dt><code>suspending</code></dt><dd>The application is suspended momentarily. This event is Android only.</dd></dl><p>For more details on the meaning of these states, see the <a href="https://api.flutter.dev/flutter/dart-ui/AppLifecycleState.html"><code>AppLifecycleStatus</code> documentation</a>.</p><div class="header-wrapper"><h2 id="layouts">Layouts</h2><a class="heading-link" href="#layouts" aria-label="Link to 'Layouts' section">#</a></div><div class="header-wrapper"><h3 id="what-is-the-equivalent-of-a-stacklayout">What is the equivalent of a StackLayout?</h3><a class="heading-link" href="#what-is-the-equivalent-of-a-stacklayout" aria-label="Link to 'What is the equivalent of a StackLayout?' section">#</a></div><p>In Xamarin.Forms you can create a <code>StackLayout</code> with an <code>Orientation</code> of horizontal or vertical. Flutter has a similar approach, however you would use the <code>Row</code> or <code>Column</code> widgets.</p><p>If you notice the two code samples are identical except the <code>Row</code> and <code>Column</code> widget. The children are the same and this feature can be exploited to develop rich layouts that can change overtime with the same children.</p> <?code-excerpt "lib/layouts.dart (row)"?> <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">@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:#BD2314"> const</span><span style="color:#0468D7"> Row</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> mainAxisAlignment: </span><span style="color:#0468D7">MainAxisAlignment</span><span style="color:#222222">.center,</span></span> <span class="line"><span style="color:#222222"> children: <</span><span style="color:#0468D7">Widget</span><span style="color:#222222">>[</span></span> <span class="line"><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'Row One'</span><span style="color:#222222">),</span></span> <span class="line"><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'Row Two'</span><span style="color:#222222">),</span></span> <span class="line"><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'Row Three'</span><span style="color:#222222">),</span></span> <span class="line"><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'Row Four'</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><?code-excerpt "lib/layouts.dart (column)"?> <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">@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:#BD2314"> const</span><span style="color:#0468D7"> Column</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> mainAxisAlignment: </span><span style="color:#0468D7">MainAxisAlignment</span><span style="color:#222222">.center,</span></span> <span class="line"><span style="color:#222222"> children: <</span><span style="color:#0468D7">Widget</span><span style="color:#222222">>[</span></span> <span class="line"><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'Column One'</span><span style="color:#222222">),</span></span> <span class="line"><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'Column Two'</span><span style="color:#222222">),</span></span> <span class="line"><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'Column Three'</span><span style="color:#222222">),</span></span> <span class="line"><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'Column Four'</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><div class="header-wrapper"><h3 id="what-is-the-equivalent-of-a-grid">What is the equivalent of a Grid?</h3><a class="heading-link" href="#what-is-the-equivalent-of-a-grid" aria-label="Link to 'What is the equivalent of a Grid?' section">#</a></div><p>The closest equivalent of a <code>Grid</code> would be a <code>GridView</code>. This is much more powerful than what you are used to in Xamarin.Forms. A <code>GridView</code> provides automatic scrolling when the content exceeds its viewable space.</p> <?code-excerpt "lib/layouts.dart (grid)"?> <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">@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"> GridView</span><span style="color:#222222">.</span><span style="color:#6200EE">count</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#6E6E70"> // Create a grid with 2 columns. If you change the scrollDirection to</span></span> <span class="line"><span style="color:#6E6E70"> // horizontal, this would produce 2 rows.</span></span> <span class="line"><span style="color:#222222"> crossAxisCount: </span><span style="color:#0C7064">2</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#6E6E70"> // Generate 100 widgets that display their index in the list.</span></span> <span class="line"><span style="color:#222222"> children: </span><span style="color:#0468D7">List</span><span style="color:#222222"><</span><span style="color:#0468D7">Widget</span><span style="color:#222222">>.</span><span style="color:#6200EE">generate</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#0C7064"> 100</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> (index) {</span></span> <span class="line"><span style="color:#BD2314"> return</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:#0C7064"> 'Item </span><span style="color:#0C7064">$</span><span style="color:#222222">index</span><span style="color:#0C7064">'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> style: </span><span style="color:#0468D7">Theme</span><span style="color:#222222">.</span><span style="color:#6200EE">of</span><span style="color:#222222">(context).textTheme.headlineMedium,</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><p>You might have used a <code>Grid</code> in Xamarin.Forms to implement widgets that overlay other widgets. In Flutter, you accomplish this with the <code>Stack</code> widget.</p><p>This sample creates two icons that overlap each other.</p> <?code-excerpt "lib/layouts.dart (stack)"?> <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">@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:#BD2314"> const</span><span style="color:#0468D7"> Stack</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> children: <</span><span style="color:#0468D7">Widget</span><span style="color:#222222">>[</span></span> <span class="line"><span style="color:#0468D7"> Icon</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#0468D7"> Icons</span><span style="color:#222222">.add_box,</span></span> <span class="line"><span style="color:#222222"> size: </span><span style="color:#0C7064">24</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">.black,</span></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#0468D7"> Positioned</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> left: </span><span style="color:#0C7064">10</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> child: </span><span style="color:#0468D7">Icon</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#0468D7"> Icons</span><span style="color:#222222">.add_circle,</span></span> <span class="line"><span style="color:#222222"> size: </span><span style="color:#0C7064">24</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">.black,</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><div class="header-wrapper"><h3 id="what-is-the-equivalent-of-a-scrollview">What is the equivalent of a ScrollView?</h3><a class="heading-link" href="#what-is-the-equivalent-of-a-scrollview" aria-label="Link to 'What is the equivalent of a ScrollView?' section">#</a></div><p>In Xamarin.Forms, a <code>ScrollView</code> wraps around a <code>VisualElement</code>, and if the content is larger than the device screen, it scrolls.</p><p>In Flutter, the closest match is the <code>SingleChildScrollView</code> widget. You simply fill the Widget with the content that you want to be scrollable.</p> <?code-excerpt "lib/layouts.dart (scroll-view)"?> <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">@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:#BD2314"> const</span><span style="color:#0468D7"> SingleChildScrollView</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 style="color:#0C7064">'Long Content'</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>If you have many items you want to wrap in a scroll, even of different <code>Widget</code> types, you might want to use a <code>ListView</code>. This might seem like overkill, but in Flutter this is far more optimized and less intensive than a Xamarin.Forms <code>ListView</code>, which is backing on to platform specific controls.</p> <?code-excerpt "lib/layouts.dart (list-view)"?> <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">@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"> ListView</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> children: </span><span style="color:#BD2314">const</span><span style="color:#222222"> <</span><span style="color:#0468D7">Widget</span><span style="color:#222222">>[</span></span> <span class="line"><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'Row One'</span><span style="color:#222222">),</span></span> <span class="line"><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'Row Two'</span><span style="color:#222222">),</span></span> <span class="line"><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'Row Three'</span><span style="color:#222222">),</span></span> <span class="line"><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'Row Four'</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><div class="header-wrapper"><h3 id="how-do-i-handle-landscape-transitions-in-flutter">How do I handle landscape transitions in Flutter?</h3><a class="heading-link" href="#how-do-i-handle-landscape-transitions-in-flutter" aria-label="Link to 'How do I handle landscape transitions in Flutter?' section">#</a></div><p>Landscape transitions can be handled automatically by setting the <code>configChanges</code> property in the AndroidManifest.xml:</p><div class="code-block-wrapper language-xml"><div class="code-block-body"><span class="code-block-language" title="Language xml">xml</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#222222"><</span><span style="color:#0468D7">activity</span><span style="color:#6200EE"> android</span><span style="color:#222222">:</span><span style="color:#6200EE">configChanges</span><span style="color:#222222">=</span><span style="color:#0C7064">"orientation|screenSize"</span><span style="color:#222222"> /></span></span></code></pre></div></div><div class="header-wrapper"><h2 id="gesture-detection-and-touch-event-handling">Gesture detection and touch event handling</h2><a class="heading-link" href="#gesture-detection-and-touch-event-handling" aria-label="Link to 'Gesture detection and touch event handling' section">#</a></div><div class="header-wrapper"><h3 id="how-do-i-add-gesturerecognizers-to-a-widget-in-flutter">How do I add GestureRecognizers to a widget in Flutter?</h3><a class="heading-link" href="#how-do-i-add-gesturerecognizers-to-a-widget-in-flutter" aria-label="Link to 'How do I add GestureRecognizers to a widget in Flutter?' section">#</a></div><p>In Xamarin.Forms, <code>Element</code>s might contain a click event you can attach to. Many elements also contain a <code>Command</code> that is tied to this event. Alternatively you would use the <code>TapGestureRecognizer</code>. In Flutter there are two very similar ways:</p><ol><li><p>If the widget supports event detection, pass a function to it and handle it in the function. For example, the ElevatedButton has an <code>onPressed</code> parameter:</p> <?code-excerpt "lib/gestures.dart (elevated-button)"?> <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">@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"> ElevatedButton</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> onPressed: () {</span></span> <span class="line"><span style="color:#222222"> developer.</span><span style="color:#6200EE">log</span><span style="color:#222222">(</span><span style="color:#0C7064">'click'</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:#BD2314">const</span><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'Button'</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></li><li><p>If the widget doesn't support event detection, wrap the widget in a <code>GestureDetector</code> and pass a function to the <code>onTap</code> parameter.</p> <?code-excerpt "lib/gestures.dart (gesture-detector)"?> <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"> SampleApp</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"> SampleApp</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"> Scaffold</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> body: </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">GestureDetector</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> onTap: () {</span></span> <span class="line"><span style="color:#222222"> developer.</span><span style="color:#6200EE">log</span><span style="color:#222222">(</span><span style="color:#0C7064">'tap'</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:#BD2314">const</span><span style="color:#0468D7"> FlutterLogo</span><span style="color:#222222">(size: </span><span style="color:#0C7064">200</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></li></ol><div class="header-wrapper"><h3 id="how-do-i-handle-other-gestures-on-widgets">How do I handle other gestures on widgets?</h3><a class="heading-link" href="#how-do-i-handle-other-gestures-on-widgets" aria-label="Link to 'How do I handle other gestures on widgets?' section">#</a></div><p>In Xamarin.Forms you would add a <code>GestureRecognizer</code> to the <code>View</code>. You would normally be limited to <code>TapGestureRecognizer</code>, <code>PinchGestureRecognizer</code>, <code>PanGestureRecognizer</code>, <code>SwipeGestureRecognizer</code>, <code>DragGestureRecognizer</code> and <code>DropGestureRecognizer</code> unless you built your own.</p><p>In Flutter, using the GestureDetector, you can listen to a wide range of Gestures such as:</p><ul><li>Tap</li></ul><dl><dt><code>onTapDown</code></dt><dd>A pointer that might cause a tap has contacted the screen at a particular location.</dd><dt><code>onTapUp</code></dt><dd>A pointer that triggers a tap has stopped contacting the screen at a particular location.</dd><dt><code>onTap</code></dt><dd>A tap has occurred.</dd><dt><code>onTapCancel</code></dt><dd>The pointer that previously triggered the <code>onTapDown</code> won't cause a tap.</dd></dl><ul><li>Double tap</li></ul><dl><dt><code>onDoubleTap</code></dt><dd>The user tapped the screen at the same location twice in quick succession.</dd></dl><ul><li>Long press</li></ul><dl><dt><code>onLongPress</code></dt><dd>A pointer has remained in contact with the screen at the same location for a long period of time.</dd></dl><ul><li>Vertical drag</li></ul><dl><dt><code>onVerticalDragStart</code></dt><dd>A pointer has contacted the screen and might begin to move vertically.</dd><dt><code>onVerticalDragUpdate</code></dt><dd>A pointer in contact with the screen has moved further in the vertical direction.</dd><dt><code>onVerticalDragEnd</code></dt><dd>A pointer that was previously in contact with the screen and moving vertically is no longer in contact with the screen and was moving at a specific velocity when it stopped contacting the screen.</dd></dl><ul><li>Horizontal drag</li></ul><dl><dt><code>onHorizontalDragStart</code></dt><dd>A pointer has contacted the screen and might begin to move horizontally.</dd><dt><code>onHorizontalDragUpdate</code></dt><dd>A pointer in contact with the screen has moved further in the horizontal direction.</dd><dt><code>onHorizontalDragEnd</code></dt><dd>A pointer that was previously in contact with the screen and moving horizontally is no longer in contact with the screen and was moving at a specific velocity when it stopped contacting the screen.</dd></dl><p>The following example shows a <code>GestureDetector</code> that rotates the Flutter logo on a double tap:</p> <?code-excerpt "lib/gestures.dart (rotating-flutter-detector)"?> <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"> RotatingFlutterDetector</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"> RotatingFlutterDetector</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">RotatingFlutterDetector</span><span style="color:#222222">> </span><span style="color:#6200EE">createState</span><span style="color:#222222">() =></span></span> <span class="line"><span style="color:#0468D7"> _RotatingFlutterDetectorState</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"> _RotatingFlutterDetectorState</span><span style="color:#BD2314"> extends</span><span style="color:#0468D7"> State</span><span style="color:#222222"><</span><span style="color:#0468D7">RotatingFlutterDetector</span><span style="color:#222222">></span></span> <span class="line"><span style="color:#BD2314"> with</span><span style="color:#0468D7"> SingleTickerProviderStateMixin</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#BD2314"> late</span><span style="color:#BD2314"> final</span><span style="color:#0468D7"> AnimationController</span><span style="color:#222222"> controller;</span></span> <span class="line"><span style="color:#BD2314"> late</span><span style="color:#BD2314"> final</span><span style="color:#0468D7"> CurvedAnimation</span><span style="color:#222222"> curve;</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> @override</span></span> <span class="line"><span style="color:#BD2314"> void</span><span style="color:#6200EE"> initState</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#BD2314"> super</span><span style="color:#222222">.</span><span style="color:#6200EE">initState</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#222222"> controller = </span><span style="color:#0468D7">AnimationController</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> duration: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> Duration</span><span style="color:#222222">(milliseconds: </span><span style="color:#0C7064">2000</span><span style="color:#222222">),</span></span> <span class="line"><span style="color:#222222"> vsync: </span><span style="color:#BD2314">this</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> );</span></span> <span class="line"><span style="color:#222222"> curve = </span><span style="color:#0468D7">CurvedAnimation</span><span style="color:#222222">(parent: controller, curve: </span><span style="color:#0468D7">Curves</span><span style="color:#222222">.easeIn);</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"> Scaffold</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> body: </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">GestureDetector</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> onDoubleTap: () {</span></span> <span class="line"><span style="color:#BD2314"> if</span><span style="color:#222222"> (controller.isCompleted) {</span></span> <span class="line"><span style="color:#222222"> controller.</span><span style="color:#6200EE">reverse</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"> controller.</span><span style="color:#6200EE">forward</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"> child: </span><span style="color:#0468D7">RotationTransition</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> turns: curve,</span></span> <span class="line"><span style="color:#222222"> child: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> FlutterLogo</span><span style="color:#222222">(size: </span><span style="color:#0C7064">200</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> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><div class="header-wrapper"><h2 id="listviews-and-adapters">Listviews and adapters</h2><a class="heading-link" href="#listviews-and-adapters" aria-label="Link to 'Listviews and adapters' section">#</a></div><div class="header-wrapper"><h3 id="what-is-the-equivalent-to-a-listview-in-flutter">What is the equivalent to a ListView in Flutter?</h3><a class="heading-link" href="#what-is-the-equivalent-to-a-listview-in-flutter" aria-label="Link to 'What is the equivalent to a ListView in Flutter?' section">#</a></div><p>The equivalent to a <code>ListView</code> in Flutter is … a <code>ListView</code>!</p><p>In a Xamarin.Forms <code>ListView</code>, you create a <code>ViewCell</code> and possibly a <code>DataTemplateSelector</code>and pass it into the <code>ListView</code>, which renders each row with what your <code>DataTemplateSelector</code> or <code>ViewCell</code> returns. However, you often have to make sure you turn on Cell Recycling otherwise you will run into memory issues and slow scrolling speeds.</p><p>Due to Flutter's immutable widget pattern, you pass a list of widgets to your <code>ListView</code>, and Flutter takes care of making sure that scrolling is fast and smooth.</p> <?code-excerpt "lib/listview.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:#BD2314">void</span><span style="color:#6200EE"> main</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#6200EE"> runApp</span><span style="color:#222222">(</span><span style="color:#BD2314">const</span><span style="color:#0468D7"> SampleApp</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"> SampleApp</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:#6E6E70"> /// This widget is the root of your application.</span></span> <span class="line"><span style="color:#BD2314"> const</span><span style="color:#0468D7"> SampleApp</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:#BD2314"> const</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">'Sample App'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> home: </span><span style="color:#0468D7">SampleAppPage</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> <span class="line"><span style="color:#BD2314">class</span><span style="color:#0468D7"> SampleAppPage</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"> SampleAppPage</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:#0468D7"> List</span><span style="color:#222222"><</span><span style="color:#0468D7">Widget</span><span style="color:#222222">> </span><span style="color:#6200EE">_getListData</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#0468D7"> List</span><span style="color:#222222"><</span><span style="color:#0468D7">Widget</span><span style="color:#222222">>.</span><span style="color:#6200EE">generate</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#0C7064"> 100</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> (index) => </span><span style="color:#0468D7">Padding</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">10</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 style="color:#0C7064">'Row </span><span style="color:#0C7064">$</span><span style="color:#222222">index</span><span style="color:#0C7064">'</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> <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"> 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">(title: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'Sample App'</span><span style="color:#222222">)),</span></span> <span class="line"><span style="color:#222222"> body: </span><span style="color:#0468D7">ListView</span><span style="color:#222222">(children: </span><span style="color:#6200EE">_getListData</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><div class="header-wrapper"><h3 id="how-do-i-know-which-list-item-has-been-clicked">How do I know which list item has been clicked?</h3><a class="heading-link" href="#how-do-i-know-which-list-item-has-been-clicked" aria-label="Link to 'How do I know which list item has been clicked?' section">#</a></div><p>In Xamarin.Forms, the ListView has an <code>ItemTapped</code> method to find out which item was clicked. There are many other techniques you might have used such as checking when <code>SelectedItem</code> or <code>EventToCommand</code> behaviors change.</p><p>In Flutter, use the touch handling provided by the passed-in widgets.</p> <?code-excerpt "lib/listview_item_clicked.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"> 'dart:developer'</span><span style="color:#BD2314"> as</span><span style="color:#222222"> developer;</span></span> <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:#BD2314">void</span><span style="color:#6200EE"> main</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#6200EE"> runApp</span><span style="color:#222222">(</span><span style="color:#BD2314">const</span><span style="color:#0468D7"> SampleApp</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"> SampleApp</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:#6E6E70"> // This widget is the root of your application.</span></span> <span class="line"><span style="color:#BD2314"> const</span><span style="color:#0468D7"> SampleApp</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:#BD2314"> const</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">'Sample App'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> home: </span><span style="color:#0468D7">SampleAppPage</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> <span class="line"><span style="color:#BD2314">class</span><span style="color:#0468D7"> SampleAppPage</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"> SampleAppPage</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">SampleAppPage</span><span style="color:#222222">> </span><span style="color:#6200EE">createState</span><span style="color:#222222">() => </span><span style="color:#0468D7">_SampleAppPageState</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"> _SampleAppPageState</span><span style="color:#BD2314"> extends</span><span style="color:#0468D7"> State</span><span style="color:#222222"><</span><span style="color:#0468D7">SampleAppPage</span><span style="color:#222222">> {</span></span> <span class="line"><span style="color:#0468D7"> List</span><span style="color:#222222"><</span><span style="color:#0468D7">Widget</span><span style="color:#222222">> </span><span style="color:#6200EE">_getListData</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#0468D7"> List</span><span style="color:#222222"><</span><span style="color:#0468D7">Widget</span><span style="color:#222222">>.</span><span style="color:#6200EE">generate</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#0C7064"> 100</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> (index) => </span><span style="color:#0468D7">GestureDetector</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> onTap: () {</span></span> <span class="line"><span style="color:#222222"> developer.</span><span style="color:#6200EE">log</span><span style="color:#222222">(</span><span style="color:#0C7064">'Row </span><span style="color:#0C7064">$</span><span style="color:#222222">index</span><span style="color:#0C7064"> tapped'</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">Padding</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">10</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 style="color:#0C7064">'Row </span><span style="color:#0C7064">$</span><span style="color:#222222">index</span><span style="color:#0C7064">'</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> <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"> 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">(title: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'Sample App'</span><span style="color:#222222">)),</span></span> <span class="line"><span style="color:#222222"> body: </span><span style="color:#0468D7">ListView</span><span style="color:#222222">(children: </span><span style="color:#6200EE">_getListData</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><div class="header-wrapper"><h3 id="how-do-i-update-a-listview-dynamically">How do I update a ListView dynamically?</h3><a class="heading-link" href="#how-do-i-update-a-listview-dynamically" aria-label="Link to 'How do I update a ListView dynamically?' section">#</a></div><p>In Xamarin.Forms, if you bound the <code>ItemsSource</code> property to an <code>ObservableCollection</code>, you would just update the list in your ViewModel. Alternatively, you could assign a new <code>List</code> to the <code>ItemSource</code> property.</p><p>In Flutter, things work a little differently. If you update the list of widgets inside a <code>setState()</code> method, you would quickly see that your data did not change visually. This is because when <code>setState()</code> is called, the Flutter rendering engine looks at the widget tree to see if anything has changed. When it gets to your <code>ListView</code>, it performs a <code>==</code> check, and determines that the two <code>ListView</code>s are the same. Nothing has changed, so no update is required.</p><p>For a simple way to update your <code>ListView</code>, create a new <code>List</code> inside of <code>setState()</code>, and copy the data from the old list to the new list. While this approach is simple, it is not recommended for large data sets, as shown in the next example.</p> <?code-excerpt "lib/dynamic_listview.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"> 'dart:developer'</span><span style="color:#BD2314"> as</span><span style="color:#222222"> developer;</span></span> <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:#BD2314">void</span><span style="color:#6200EE"> main</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#6200EE"> runApp</span><span style="color:#222222">(</span><span style="color:#BD2314">const</span><span style="color:#0468D7"> SampleApp</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"> SampleApp</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:#6E6E70"> /// This widget is the root of your application.</span></span> <span class="line"><span style="color:#BD2314"> const</span><span style="color:#0468D7"> SampleApp</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:#BD2314"> const</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">'Sample App'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> home: </span><span style="color:#0468D7">SampleAppPage</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> <span class="line"><span style="color:#BD2314">class</span><span style="color:#0468D7"> SampleAppPage</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"> SampleAppPage</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">SampleAppPage</span><span style="color:#222222">> </span><span style="color:#6200EE">createState</span><span style="color:#222222">() => </span><span style="color:#0468D7">_SampleAppPageState</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"> _SampleAppPageState</span><span style="color:#BD2314"> extends</span><span style="color:#0468D7"> State</span><span style="color:#222222"><</span><span style="color:#0468D7">SampleAppPage</span><span style="color:#222222">> {</span></span> <span class="line"><span style="color:#0468D7"> List</span><span style="color:#222222"><</span><span style="color:#0468D7">Widget</span><span style="color:#222222">> widgets = <</span><span style="color:#0468D7">Widget</span><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:#BD2314"> void</span><span style="color:#6200EE"> initState</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#BD2314"> super</span><span style="color:#222222">.</span><span style="color:#6200EE">initState</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#BD2314"> for</span><span style="color:#222222"> (</span><span style="color:#0468D7">int</span><span style="color:#222222"> i = </span><span style="color:#0C7064">0</span><span style="color:#222222">; i < </span><span style="color:#0C7064">100</span><span style="color:#222222">; i++) {</span></span> <span class="line"><span style="color:#222222"> widgets.</span><span style="color:#6200EE">add</span><span style="color:#222222">(</span><span style="color:#6200EE">getRow</span><span style="color:#222222">(i));</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:#0468D7"> Widget</span><span style="color:#6200EE"> getRow</span><span style="color:#222222">(</span><span style="color:#0468D7">int</span><span style="color:#222222"> index) {</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: () {</span></span> <span class="line"><span style="color:#6200EE"> setState</span><span style="color:#222222">(() {</span></span> <span class="line"><span style="color:#222222"> widgets = </span><span style="color:#0468D7">List</span><span style="color:#222222"><</span><span style="color:#0468D7">Widget</span><span style="color:#222222">>.</span><span style="color:#6200EE">from</span><span style="color:#222222">(widgets);</span></span> <span class="line"><span style="color:#222222"> widgets.</span><span style="color:#6200EE">add</span><span style="color:#222222">(</span><span style="color:#6200EE">getRow</span><span style="color:#222222">(widgets.length));</span></span> <span class="line"><span style="color:#222222"> developer.</span><span style="color:#6200EE">log</span><span style="color:#222222">(</span><span style="color:#0C7064">'Row </span><span style="color:#0C7064">$</span><span style="color:#222222">index</span><span style="color:#0C7064">'</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"> child: </span><span style="color:#0468D7">Padding</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">10</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 style="color:#0C7064">'Row </span><span style="color:#0C7064">$</span><span style="color:#222222">index</span><span style="color:#0C7064">'</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> <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"> 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">(title: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'Sample App'</span><span style="color:#222222">)),</span></span> <span class="line"><span style="color:#222222"> body: </span><span style="color:#0468D7">ListView</span><span style="color:#222222">(children: widgets),</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>The recommended, efficient, and effective way to build a list uses a <code>ListView.Builder</code>. This method is great when you have a dynamic list or a list with very large amounts of data. This is essentially the equivalent of RecyclerView on Android, which automatically recycles list elements for you:</p> <?code-excerpt "lib/listview_builder.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"> 'dart:developer'</span><span style="color:#BD2314"> as</span><span style="color:#222222"> developer;</span></span> <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:#BD2314">void</span><span style="color:#6200EE"> main</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#6200EE"> runApp</span><span style="color:#222222">(</span><span style="color:#BD2314">const</span><span style="color:#0468D7"> SampleApp</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"> SampleApp</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:#6E6E70"> /// This widget is the root of your application.</span></span> <span class="line"><span style="color:#BD2314"> const</span><span style="color:#0468D7"> SampleApp</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:#BD2314"> const</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">'Sample App'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> home: </span><span style="color:#0468D7">SampleAppPage</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> <span class="line"><span style="color:#BD2314">class</span><span style="color:#0468D7"> SampleAppPage</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"> SampleAppPage</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">SampleAppPage</span><span style="color:#222222">> </span><span style="color:#6200EE">createState</span><span style="color:#222222">() => </span><span style="color:#0468D7">_SampleAppPageState</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"> _SampleAppPageState</span><span style="color:#BD2314"> extends</span><span style="color:#0468D7"> State</span><span style="color:#222222"><</span><span style="color:#0468D7">SampleAppPage</span><span style="color:#222222">> {</span></span> <span class="line"><span style="color:#0468D7"> List</span><span style="color:#222222"><</span><span style="color:#0468D7">Widget</span><span style="color:#222222">> widgets = [];</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> @override</span></span> <span class="line"><span style="color:#BD2314"> void</span><span style="color:#6200EE"> initState</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#BD2314"> super</span><span style="color:#222222">.</span><span style="color:#6200EE">initState</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#BD2314"> for</span><span style="color:#222222"> (</span><span style="color:#0468D7">int</span><span style="color:#222222"> i = </span><span style="color:#0C7064">0</span><span style="color:#222222">; i < </span><span style="color:#0C7064">100</span><span style="color:#222222">; i++) {</span></span> <span class="line"><span style="color:#222222"> widgets.</span><span style="color:#6200EE">add</span><span style="color:#222222">(</span><span style="color:#6200EE">getRow</span><span style="color:#222222">(i));</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:#0468D7"> Widget</span><span style="color:#6200EE"> getRow</span><span style="color:#222222">(</span><span style="color:#0468D7">int</span><span style="color:#222222"> index) {</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: () {</span></span> <span class="line"><span style="color:#6200EE"> setState</span><span style="color:#222222">(() {</span></span> <span class="line"><span style="color:#222222"> widgets.</span><span style="color:#6200EE">add</span><span style="color:#222222">(</span><span style="color:#6200EE">getRow</span><span style="color:#222222">(widgets.length));</span></span> <span class="line"><span style="color:#222222"> developer.</span><span style="color:#6200EE">log</span><span style="color:#222222">(</span><span style="color:#0C7064">'Row </span><span style="color:#0C7064">$</span><span style="color:#222222">index</span><span style="color:#0C7064">'</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"> child: </span><span style="color:#0468D7">Padding</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">10</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 style="color:#0C7064">'Row </span><span style="color:#0C7064">$</span><span style="color:#222222">index</span><span style="color:#0C7064">'</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> <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"> 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">(title: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'Sample App'</span><span style="color:#222222">)),</span></span> <span class="line"><span style="color:#222222"> body: </span><span style="color:#0468D7">ListView</span><span style="color:#222222">.</span><span style="color:#6200EE">builder</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> itemCount: widgets.length,</span></span> <span class="line"><span style="color:#222222"> itemBuilder: (context, index) {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#6200EE"> getRow</span><span style="color:#222222">(index);</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>Instead of creating a <code>ListView</code>, create a <code>ListView.builder</code> that takes two key parameters: the initial length of the list, and an item builder function.</p><p>The item builder function is similar to the <code>getView</code> function in an Android adapter; it takes a position, and returns the row you want rendered at that position.</p><p>Finally, but most importantly, notice that the <code>onTap()</code> function doesn't recreate the list anymore, but instead adds to it.</p><p>For more information, see <a href="https://codelabs.developers.google.com/codelabs/flutter-codelab-first">Your first Flutter app</a> codelab.</p><div class="header-wrapper"><h2 id="working-with-text">Working with text</h2><a class="heading-link" href="#working-with-text" aria-label="Link to 'Working with text' section">#</a></div><div class="header-wrapper"><h3 id="how-do-i-set-custom-fonts-on-my-text-widgets">How do I set custom fonts on my text widgets?</h3><a class="heading-link" href="#how-do-i-set-custom-fonts-on-my-text-widgets" aria-label="Link to 'How do I set custom fonts on my text widgets?' section">#</a></div><p>In Xamarin.Forms, you would have to add a custom font in each native project. Then, in your <code>Element</code> you would assign this font name to the <code>FontFamily</code> attribute using <code>filename#fontname</code> and just <code>fontname</code> for iOS.</p><p>In Flutter, place the font file in a folder and reference it in the <code>pubspec.yaml</code> file, similar to how you import images.</p><div class="code-block-wrapper language-yaml"><div class="code-block-body"><span class="code-block-language" title="Language yaml">yaml</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#0468D7">fonts</span><span style="color:#222222">:</span></span> <span class="line"><span style="color:#222222"> - </span><span style="color:#0468D7">family</span><span style="color:#222222">: </span><span style="color:#0C7064">MyCustomFont</span></span> <span class="line"><span style="color:#0468D7"> fonts</span><span style="color:#222222">:</span></span> <span class="line"><span style="color:#222222"> - </span><span style="color:#0468D7">asset</span><span style="color:#222222">: </span><span style="color:#0C7064">fonts/MyCustomFont.ttf</span></span> <span class="line"><span style="color:#222222"> - </span><span style="color:#0468D7">style</span><span style="color:#222222">: </span><span style="color:#0C7064">italic</span></span></code></pre></div></div><p>Then assign the font to your <code>Text</code> widget:</p> <?code-excerpt "lib/strings.dart (custom-font)"?> <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">@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"> 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">(title: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'Sample App'</span><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">Text</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#0C7064"> 'This is a custom font text'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> style: </span><span style="color:#0468D7">TextStyle</span><span style="color:#222222">(fontFamily: </span><span style="color:#0C7064">'MyCustomFont'</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></code></pre></div></div><div class="header-wrapper"><h3 id="how-do-i-style-my-text-widgets">How do I style my text widgets?</h3><a class="heading-link" href="#how-do-i-style-my-text-widgets" aria-label="Link to 'How do I style my text widgets?' section">#</a></div><p>Along with fonts, you can customize other styling elements on a <code>Text</code> widget. The style parameter of a <code>Text</code> widget takes a <code>TextStyle</code> object, where you can customize many parameters, such as:</p><ul><li><code>color</code></li><li><code>decoration</code></li><li><code>decorationColor</code></li><li><code>decorationStyle</code></li><li><code>fontFamily</code></li><li><code>fontSize</code></li><li><code>fontStyle</code></li><li><code>fontWeight</code></li><li><code>hashCode</code></li><li><code>height</code></li><li><code>inherit</code></li><li><code>letterSpacing</code></li><li><code>textBaseline</code></li><li><code>wordSpacing</code></li></ul><div class="header-wrapper"><h2 id="form-input">Form input</h2><a class="heading-link" href="#form-input" aria-label="Link to 'Form input' section">#</a></div><div class="header-wrapper"><h3 id="how-do-i-retrieve-user-input">How do I retrieve user input?</h3><a class="heading-link" href="#how-do-i-retrieve-user-input" aria-label="Link to 'How do I retrieve user input?' section">#</a></div><p>Xamarin.Forms <code>element</code>s allow you to directly query the <code>element</code> to determine the state of its properties, or whether it's bound to a property in a <code>ViewModel</code>.</p><p>Retrieving information in Flutter is handled by specialized widgets and is different from how you are used to. If you have a <code>TextField</code>or a <code>TextFormField</code>, you can supply a <a href="https://api.flutter.dev/flutter/widgets/TextEditingController-class.html"><code>TextEditingController</code></a> to retrieve user input:</p> <?code-excerpt "lib/form.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:#BD2314">class</span><span style="color:#0468D7"> MyForm</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"> MyForm</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">MyForm</span><span style="color:#222222">> </span><span style="color:#6200EE">createState</span><span style="color:#222222">() => </span><span style="color:#0468D7">_MyFormState</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"> _MyFormState</span><span style="color:#BD2314"> extends</span><span style="color:#0468D7"> State</span><span style="color:#222222"><</span><span style="color:#0468D7">MyForm</span><span style="color:#222222">> {</span></span> <span class="line"><span style="color:#6E6E70"> /// Create a text controller and use it to retrieve the current value</span></span> <span class="line"><span style="color:#6E6E70"> /// of the TextField.</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> TextEditingController</span><span style="color:#222222"> myController = </span><span style="color:#0468D7">TextEditingController</span><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:#BD2314"> void</span><span style="color:#6200EE"> dispose</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#6E6E70"> // Clean up the controller when disposing of the widget.</span></span> <span class="line"><span style="color:#222222"> myController.</span><span style="color:#6200EE">dispose</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#BD2314"> super</span><span style="color:#222222">.</span><span style="color:#6200EE">dispose</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"> @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"> 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">(title: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'Retrieve Text Input'</span><span style="color:#222222">)),</span></span> <span class="line"><span style="color:#222222"> body: </span><span style="color:#0468D7">Padding</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">16</span><span style="color:#222222">),</span></span> <span class="line"><span style="color:#222222"> child: </span><span style="color:#0468D7">TextField</span><span style="color:#222222">(controller: myController),</span></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#222222"> floatingActionButton: </span><span style="color:#0468D7">FloatingActionButton</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#6E6E70"> // When the user presses the button, show an alert dialog with the</span></span> <span class="line"><span style="color:#6E6E70"> // text that the user has typed into our text field.</span></span> <span class="line"><span style="color:#222222"> onPressed: () {</span></span> <span class="line"><span style="color:#6200EE"> showDialog</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> context: context,</span></span> <span class="line"><span style="color:#222222"> builder: (context) {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#0468D7"> AlertDialog</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#6E6E70"> // Retrieve the text that the user has entered using the</span></span> <span class="line"><span style="color:#6E6E70"> // TextEditingController.</span></span> <span class="line"><span style="color:#222222"> content: </span><span style="color:#0468D7">Text</span><span style="color:#222222">(myController.text),</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"> tooltip: </span><span style="color:#0C7064">'Show me the value!'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> child: </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">.text_fields),</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>You can find more information and the full code listing in <a href="/cookbook/forms/retrieve-input">Retrieve the value of a text field</a>, from the <a href="/cookbook">Flutter cookbook</a>.</p><div class="header-wrapper"><h3 id="what-is-the-equivalent-of-a-placeholder-on-an-entry">What is the equivalent of a Placeholder on an Entry?</h3><a class="heading-link" href="#what-is-the-equivalent-of-a-placeholder-on-an-entry" aria-label="Link to 'What is the equivalent of a Placeholder on an Entry?' section">#</a></div><p>In Xamarin.Forms, some <code>Elements</code> support a <code>Placeholder</code> property that you can assign a value to. For example:</p><div class="code-block-wrapper language-xml"><div class="code-block-body"><span class="code-block-language" title="Language xml">xml</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#222222"><</span><span style="color:#0468D7">Entry</span><span style="color:#6200EE"> Placeholder</span><span style="color:#222222">=</span><span style="color:#0C7064">"This is a hint"</span><span style="color:#222222">></span></span></code></pre></div></div><p>In Flutter, you can easily show a "hint" or a placeholder text for your input by adding an <code>InputDecoration</code> object to the <code>decoration</code> constructor parameter for the text widget.</p> <?code-excerpt "lib/input_decoration.dart (hint-text)" replace="/child: //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:#0468D7">TextField</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> decoration: </span><span style="color:#0468D7">InputDecoration</span><span style="color:#222222">(hintText: </span><span style="color:#0C7064">'This is a hint'</span><span style="color:#222222">),</span></span> <span class="line"><span style="color:#222222">),</span></span></code></pre></div></div><div class="header-wrapper"><h3 id="how-do-i-show-validation-errors">How do I show validation errors?</h3><a class="heading-link" href="#how-do-i-show-validation-errors" aria-label="Link to 'How do I show validation errors?' section">#</a></div><p>With Xamarin.Forms, if you wished to provide a visual hint of a validation error, you would need to create new properties and <code>VisualElement</code>s surrounding the <code>Element</code>s that had validation errors.</p><p>In Flutter, you pass through an InputDecoration object to the decoration constructor for the text widget.</p><p>However, you don't want to start off by showing an error. Instead, when the user has entered invalid data, update the state, and pass a new <code>InputDecoration</code> object.</p> <?code-excerpt "lib/validation.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:#BD2314">void</span><span style="color:#6200EE"> main</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#6200EE"> runApp</span><span style="color:#222222">(</span><span style="color:#BD2314">const</span><span style="color:#0468D7"> SampleApp</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"> SampleApp</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:#6E6E70"> /// This widget is the root of your application.</span></span> <span class="line"><span style="color:#BD2314"> const</span><span style="color:#0468D7"> SampleApp</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:#BD2314"> const</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">'Sample App'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> home: </span><span style="color:#0468D7">SampleAppPage</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> <span class="line"><span style="color:#BD2314">class</span><span style="color:#0468D7"> SampleAppPage</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"> SampleAppPage</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">SampleAppPage</span><span style="color:#222222">> </span><span style="color:#6200EE">createState</span><span style="color:#222222">() => </span><span style="color:#0468D7">_SampleAppPageState</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"> _SampleAppPageState</span><span style="color:#BD2314"> extends</span><span style="color:#0468D7"> State</span><span style="color:#222222"><</span><span style="color:#0468D7">SampleAppPage</span><span style="color:#222222">> {</span></span> <span class="line"><span style="color:#0468D7"> String</span><span style="color:#222222">? _errorText;</span></span> <span class="line"></span> <span class="line"><span style="color:#0468D7"> String</span><span style="color:#222222">? </span><span style="color:#6200EE">_getErrorText</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#222222"> _errorText;</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"></span> <span class="line"><span style="color:#0468D7"> bool</span><span style="color:#6200EE"> isEmail</span><span style="color:#222222">(</span><span style="color:#0468D7">String</span><span style="color:#222222"> em) {</span></span> <span class="line"><span style="color:#BD2314"> const</span><span style="color:#0468D7"> String</span><span style="color:#222222"> emailRegexp =</span></span> <span class="line"><span style="color:#0C7064"> r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|'</span></span> <span class="line"><span style="color:#0C7064"> r'(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|'</span></span> <span class="line"><span style="color:#0C7064"> r'(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$'</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#0468D7"> RegExp</span><span style="color:#222222"> regExp = </span><span style="color:#0468D7">RegExp</span><span style="color:#222222">(emailRegexp);</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#222222"> regExp.</span><span style="color:#6200EE">hasMatch</span><span style="color:#222222">(em);</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"> 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">(title: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'Sample App'</span><span style="color:#222222">)),</span></span> <span class="line"><span style="color:#222222"> body: </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">TextField</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> onSubmitted: (text) {</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"> (!</span><span style="color:#6200EE">isEmail</span><span style="color:#222222">(text)) {</span></span> <span class="line"><span style="color:#222222"> _errorText = </span><span style="color:#0C7064">'Error: This is not an email'</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"> _errorText = </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"> });</span></span> <span class="line"><span style="color:#222222"> },</span></span> <span class="line"><span style="color:#222222"> decoration: </span><span style="color:#0468D7">InputDecoration</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> hintText: </span><span style="color:#0C7064">'This is a hint'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> errorText: </span><span style="color:#6200EE">_getErrorText</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> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><div class="header-wrapper"><h2 id="flutter-plugins">Flutter plugins</h2><a class="heading-link" href="#flutter-plugins" aria-label="Link to 'Flutter plugins' section">#</a></div><div class="header-wrapper"><h2 id="interacting-with-hardware-third-party-services-and-the-platform">Interacting with hardware, third party services, and the platform</h2><a class="heading-link" href="#interacting-with-hardware-third-party-services-and-the-platform" aria-label="Link to 'Interacting with hardware, third party services, and the platform' section">#</a></div><div class="header-wrapper"><h3 id="how-do-i-interact-with-the-platform-and-with-platform-native-code">How do I interact with the platform, and with platform native code?</h3><a class="heading-link" href="#how-do-i-interact-with-the-platform-and-with-platform-native-code" aria-label="Link to 'How do I interact with the platform, and with platform native code?' section">#</a></div><p>Flutter doesn't run code directly on the underlying platform; rather, the Dart code that makes up a Flutter app is run natively on the device, "sidestepping" the SDK provided by the platform. That means, for example, when you perform a network request in Dart, it runs directly in the Dart context. You don't use the Android or iOS APIs you normally take advantage of when writing native apps. Your Flutter app is still hosted in a native app's <code>ViewController</code> or <code>Activity</code> as a view, but you don't have direct access to this, or the native framework.</p><p>This doesn't mean Flutter apps can't interact with those native APIs, or with any native code you have. Flutter provides <a href="/platform-integration/platform-channels">platform channels</a> that communicate and exchange data with the <code>ViewController</code> or <code>Activity</code> that hosts your Flutter view. Platform channels are essentially an asynchronous messaging mechanism that bridges the Dart code with the host <code>ViewController</code> or <code>Activity</code> and the iOS or Android framework it runs on. You can use platform channels to execute a method on the native side, or to retrieve some data from the device's sensors, for example.</p><p>In addition to directly using platform channels, you can use a variety of pre-made <a href="/packages-and-plugins/using-packages">plugins</a> that encapsulate the native and Dart code for a specific goal. For example, you can use a plugin to access the camera roll and the device camera directly from Flutter, without having to write your own integration. Plugins are found on <a href="https://pub.dev">pub.dev</a>, Dart and Flutter's open source package repository. Some packages might support native integrations on iOS, or Android, or both.</p><p>If you can't find a plugin on pub.dev that fits your needs, you can <a href="/packages-and-plugins/developing-packages">write your own</a>, and <a href="/packages-and-plugins/developing-packages#publish">publish it on pub.dev</a>.</p><div class="header-wrapper"><h3 id="how-do-i-access-the-gps-sensor">How do I access the GPS sensor?</h3><a class="heading-link" href="#how-do-i-access-the-gps-sensor" aria-label="Link to 'How do I access the GPS sensor?' section">#</a></div><p>Use the <a href="https://pub.dev/packages/geolocator"><code>geolocator</code></a> community plugin.</p><div class="header-wrapper"><h3 id="how-do-i-access-the-camera">How do I access the camera?</h3><a class="heading-link" href="#how-do-i-access-the-camera" aria-label="Link to 'How do I access the camera?' section">#</a></div><p>The <a href="https://pub.dev/packages/camera"><code>camera</code></a> plugin is popular for accessing the camera.</p><div class="header-wrapper"><h3 id="how-do-i-log-in-with-facebook">How do I log in with Facebook?</h3><a class="heading-link" href="#how-do-i-log-in-with-facebook" aria-label="Link to 'How do I log in with Facebook?' section">#</a></div><p>To log in with Facebook, use the <a href="https://pub.dev/packages/flutter_facebook_login"><code>flutter_facebook_login</code></a> community plugin.</p><div class="header-wrapper"><h3 id="how-do-i-use-firebase-features">How do I use Firebase features?</h3><a class="heading-link" href="#how-do-i-use-firebase-features" aria-label="Link to 'How do I use Firebase features?' section">#</a></div><p>Most Firebase functions are covered by <a href="https://pub.dev/flutter/packages?q=firebase">first party plugins</a>. These plugins are first-party integrations, maintained by the Flutter team:</p><ul><li><a href="https://pub.dev/packages/google_mobile_ads"><code>google_mobile_ads</code></a> for Google Mobile Ads for Flutter</li><li><a href="https://pub.dev/packages/firebase_analytics"><code>firebase_analytics</code></a> for Firebase Analytics</li><li><a href="https://pub.dev/packages/firebase_auth"><code>firebase_auth</code></a> for Firebase Auth</li><li><a href="https://pub.dev/packages/firebase_database"><code>firebase_database</code></a> for Firebase RTDB</li><li><a href="https://pub.dev/packages/firebase_storage"><code>firebase_storage</code></a> for Firebase Cloud Storage</li><li><a href="https://pub.dev/packages/firebase_messaging"><code>firebase_messaging</code></a> for Firebase Messaging (FCM)</li><li><a href="https://pub.dev/packages/flutter_firebase_ui"><code>flutter_firebase_ui</code></a> for quick Firebase Auth integrations (Facebook, Google, Twitter and email)</li><li><a href="https://pub.dev/packages/cloud_firestore"><code>cloud_firestore</code></a> for Firebase Cloud Firestore</li></ul><p>You can also find some third-party Firebase plugins on pub.dev that cover areas not directly covered by the first-party plugins.</p><div class="header-wrapper"><h3 id="how-do-i-build-my-own-custom-native-integrations">How do I build my own custom native integrations?</h3><a class="heading-link" href="#how-do-i-build-my-own-custom-native-integrations" aria-label="Link to 'How do I build my own custom native integrations?' section">#</a></div><p>If there is platform-specific functionality that Flutter or its community plugins are missing, you can build your own following the <a href="/packages-and-plugins/developing-packages">developing packages and plugins</a> page.</p><p>Flutter's plugin architecture, in a nutshell, is much like using an Event bus in Android: you fire off a message and let the receiver process and emit a result back to you. In this case, the receiver is code running on the native side on Android or iOS.</p><div class="header-wrapper"><h2 id="themes-styles">Themes (Styles)</h2><a class="heading-link" href="#themes-styles" aria-label="Link to 'Themes (Styles)' section">#</a></div><div class="header-wrapper"><h3 id="how-do-i-theme-my-app">How do I theme my app?</h3><a class="heading-link" href="#how-do-i-theme-my-app" aria-label="Link to 'How do I theme my app?' section">#</a></div><p>Flutter comes with a beautiful, built-in implementation of Material Design, which handles much of the styling and theming needs that you would typically do.</p><p>Xamarin.Forms does have a global <code>ResourceDictionary</code> where you can share styles across your app. Alternatively, there is Theme support currently in preview.</p><p>In Flutter, you declare themes in the top level widget.</p><p>To take full advantage of Material Components in your app, you can declare a top level widget <code>MaterialApp</code> as the entry point to your application. <code>MaterialApp</code> is a convenience widget that wraps a number of widgets that are commonly required for applications implementing Material Design. It builds upon a <code>WidgetsApp</code> by adding Material-specific functionality.</p><p>You can also use a <code>WidgetsApp</code> as your app widget, which provides some of the same functionality, but is not as rich as <code>MaterialApp</code>.</p><p>To customize the colors and styles of any child components, pass a <code>ThemeData</code> object to the <code>MaterialApp</code> widget. For example, in the following code, the color scheme from seed is set to deepPurple and text selection color is red.</p> <?code-excerpt "lib/theme.dart (theme)"?> <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"> SampleApp</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:#6E6E70"> /// This widget is the root of your application.</span></span> <span class="line"><span style="color:#BD2314"> const</span><span style="color:#0468D7"> SampleApp</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">'Sample App'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> theme: </span><span style="color:#0468D7">ThemeData</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> colorScheme: </span><span style="color:#0468D7">ColorScheme</span><span style="color:#222222">.</span><span style="color:#6200EE">fromSeed</span><span style="color:#222222">(seedColor: </span><span style="color:#0468D7">Colors</span><span style="color:#222222">.deepPurple),</span></span> <span class="line"><span style="color:#222222"> textSelectionTheme:</span></span> <span class="line"><span style="color:#BD2314"> const</span><span style="color:#0468D7"> TextSelectionThemeData</span><span style="color:#222222">(selectionColor: </span><span style="color:#0468D7">Colors</span><span style="color:#222222">.red),</span></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#222222"> home: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> SampleAppPage</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><div class="header-wrapper"><h2 id="databases-and-local-storage">Databases and local storage</h2><a class="heading-link" href="#databases-and-local-storage" aria-label="Link to 'Databases and local storage' section">#</a></div><div class="header-wrapper"><h3 id="how-do-i-access-shared-preferences-or-userdefaults">How do I access shared preferences or UserDefaults?</h3><a class="heading-link" href="#how-do-i-access-shared-preferences-or-userdefaults" aria-label="Link to 'How do I access shared preferences or UserDefaults?' section">#</a></div><p>Xamarin.Forms developers will likely be familiar with the <code>Xam.Plugins.Settings</code> plugin.</p><p>In Flutter, access equivalent functionality using the <a href="https://pub.dev/packages/shared_preferences"><code>shared_preferences</code></a> plugin. This plugin wraps the functionality of both <code>UserDefaults</code> and the Android equivalent, <code>SharedPreferences</code>.</p><div class="header-wrapper"><h3 id="how-do-i-access-sqlite-in-flutter">How do I access SQLite in Flutter?</h3><a class="heading-link" href="#how-do-i-access-sqlite-in-flutter" aria-label="Link to 'How do I access SQLite in Flutter?' section">#</a></div><p>In Xamarin.Forms most applications would use the <code>sqlite-net-pcl</code> plugin to access SQLite databases.</p><p>In Flutter, on macOS, Android, and iOS, access this functionality using the <a href="https://pub.dev/packages/sqflite"><code>sqflite</code></a> plugin.</p><div class="header-wrapper"><h2 id="debugging">Debugging</h2><a class="heading-link" href="#debugging" aria-label="Link to 'Debugging' section">#</a></div><div class="header-wrapper"><h3 id="what-tools-can-i-use-to-debug-my-app-in-flutter">What tools can I use to debug my app in Flutter?</h3><a class="heading-link" href="#what-tools-can-i-use-to-debug-my-app-in-flutter" aria-label="Link to 'What tools can I use to debug my app in Flutter?' section">#</a></div><p>Use the <a href="/tools/devtools">DevTools</a> suite for debugging Flutter or Dart apps.</p><p>DevTools includes support for profiling, examining the heap, inspecting the widget tree, logging diagnostics, debugging, observing executed lines of code, debugging memory leaks and memory fragmentation. For more information, check out the <a href="/tools/devtools">DevTools</a> documentation.</p><div class="header-wrapper"><h2 id="notifications">Notifications</h2><a class="heading-link" href="#notifications" aria-label="Link to 'Notifications' section">#</a></div><div class="header-wrapper"><h3 id="how-do-i-set-up-push-notifications">How do I set up push notifications?</h3><a class="heading-link" href="#how-do-i-set-up-push-notifications" aria-label="Link to 'How do I set up push notifications?' section">#</a></div><p>In Android, you use Firebase Cloud Messaging to set up push notifications for your app.</p><p>In Flutter, access this functionality using the <a href="https://pub.dev/packages/firebase_messaging"><code>firebase_messaging</code></a> plugin. For more information on using the Firebase Cloud Messaging API, see the <a href="https://pub.dev/packages/firebase_messaging"><code>firebase_messaging</code></a> plugin documentation.</p><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-06-24.</span> <a href="https://github.com/flutter/website/tree/main/src/content/get-started/flutter-for/xamarin-forms-devs.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/get-started/flutter-for/xamarin-forms-devs/&page-source=https://github.com/flutter/website/tree/main/src/content/get-started/flutter-for/xamarin-forms-devs.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>