CINXE.COM
Android Compose Tutorial | Jetpack Compose | Android Developers
<!doctype html> <html lang="en" dir="ltr"> <head> <meta name="google-signin-client-id" content="721724668570-nbkv1cfusk7kk4eni4pjvepaus73b13t.apps.googleusercontent.com"> <meta name="google-signin-scope" content="profile email https://www.googleapis.com/auth/developerprofiles https://www.googleapis.com/auth/developerprofiles.award"> <meta property="og:site_name" content="Android Developers"> <meta property="og:type" content="website"><meta name="theme-color" content="#34a853"><meta charset="utf-8"> <meta content="IE=Edge" http-equiv="X-UA-Compatible"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="manifest" href="/_pwa/android/manifest.json" crossorigin="use-credentials"> <link rel="preconnect" href="//www.gstatic.com" crossorigin> <link rel="preconnect" href="//fonts.gstatic.com" crossorigin> <link rel="preconnect" href="//fonts.googleapis.com" crossorigin> <link rel="preconnect" href="//apis.google.com" crossorigin> <link rel="preconnect" href="//www.google-analytics.com" crossorigin><link rel="stylesheet" href="//fonts.googleapis.com/css?family=Google+Sans:400,500,600,700|Google+Sans+Text:400,400italic,500,500italic,600,600italic,700,700italic|Roboto+Mono:400,500,700&display=swap"> <link rel="stylesheet" href="//fonts.googleapis.com/css2?family=Material+Icons&family=Material+Symbols+Outlined&display=block"><link rel="stylesheet" href="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/android/css/app.css"> <link rel="stylesheet" href="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/android/css/dark-theme.css" disabled> <link rel="shortcut icon" href="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/android/images/favicon.svg"> <link rel="apple-touch-icon" href="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/android/images/touchicon-180.png"><link rel="canonical" href="https://developer.android.com/develop/ui/compose/tutorial"><link rel="search" type="application/opensearchdescription+xml" title="Android Developers" href="https://developer.android.com/s/opensearch.xml"> <link rel="alternate" hreflang="en" href="https://developer.android.com/develop/ui/compose/tutorial" /><link rel="alternate" hreflang="x-default" href="https://developer.android.com/develop/ui/compose/tutorial" /><link rel="alternate" hreflang="ar" href="https://developer.android.com/develop/ui/compose/tutorial?hl=ar" /><link rel="alternate" hreflang="bn" href="https://developer.android.com/develop/ui/compose/tutorial?hl=bn" /><link rel="alternate" hreflang="zh-Hans" href="https://developer.android.com/develop/ui/compose/tutorial?hl=zh-cn" /><link rel="alternate" hreflang="zh-Hant" href="https://developer.android.com/develop/ui/compose/tutorial?hl=zh-tw" /><link rel="alternate" hreflang="fa" href="https://developer.android.com/develop/ui/compose/tutorial?hl=fa" /><link rel="alternate" hreflang="fr" href="https://developer.android.com/develop/ui/compose/tutorial?hl=fr" /><link rel="alternate" hreflang="de" href="https://developer.android.com/develop/ui/compose/tutorial?hl=de" /><link rel="alternate" hreflang="he" href="https://developer.android.com/develop/ui/compose/tutorial?hl=he" /><link rel="alternate" hreflang="hi" href="https://developer.android.com/develop/ui/compose/tutorial?hl=hi" /><link rel="alternate" hreflang="id" href="https://developer.android.com/develop/ui/compose/tutorial?hl=id" /><link rel="alternate" hreflang="it" href="https://developer.android.com/develop/ui/compose/tutorial?hl=it" /><link rel="alternate" hreflang="ja" href="https://developer.android.com/develop/ui/compose/tutorial?hl=ja" /><link rel="alternate" hreflang="ko" href="https://developer.android.com/develop/ui/compose/tutorial?hl=ko" /><link rel="alternate" hreflang="pl" href="https://developer.android.com/develop/ui/compose/tutorial?hl=pl" /><link rel="alternate" hreflang="pt-BR" href="https://developer.android.com/develop/ui/compose/tutorial?hl=pt-br" /><link rel="alternate" hreflang="ru" href="https://developer.android.com/develop/ui/compose/tutorial?hl=ru" /><link rel="alternate" hreflang="es-419" href="https://developer.android.com/develop/ui/compose/tutorial?hl=es-419" /><link rel="alternate" hreflang="th" href="https://developer.android.com/develop/ui/compose/tutorial?hl=th" /><link rel="alternate" hreflang="tr" href="https://developer.android.com/develop/ui/compose/tutorial?hl=tr" /><link rel="alternate" hreflang="vi" href="https://developer.android.com/develop/ui/compose/tutorial?hl=vi" /><title>Android Compose Tutorial | Jetpack Compose | Android Developers</title> <meta property="og:title" content="Android Compose Tutorial | Jetpack Compose | Android Developers"><meta property="og:url" content="https://developer.android.com/develop/ui/compose/tutorial"><meta property="og:image" content="https://developer.android.com/static/images/social/android-developers.png"> <meta property="og:image:width" content="1200"> <meta property="og:image:height" content="675"><meta property="og:locale" content="en"><meta name="twitter:card" content="summary_large_image"><script type="application/ld+json"> { "@context": "https://schema.org", "@type": "Article", "headline": "Android Compose Tutorial" } </script><script type="application/ld+json"> { "@context": "https://schema.org", "@type": "BreadcrumbList", "itemListElement": [{ "@type": "ListItem", "position": 1, "name": "Develop", "item": "https://developer.android.com/develop" },{ "@type": "ListItem", "position": 2, "name": "Core areas", "item": "https://developer.android.com/develop/core-areas" },{ "@type": "ListItem", "position": 3, "name": "UI", "item": "https://developer.android.com/develop/ui" },{ "@type": "ListItem", "position": 4, "name": "Android Compose Tutorial", "item": "https://developer.android.com/develop/ui/compose/tutorial" }] } </script> <link rel="stylesheet" href="/extras.css"></head> <body class="dac-tutorial-page b" template="landing" theme="android-theme" type="article" appearance layout="full" pending> <devsite-progress type="indeterminate" id="app-progress"></devsite-progress> <section class="devsite-wrapper"> <devsite-cookie-notification-bar></devsite-cookie-notification-bar><devsite-header role="banner"> <div class="devsite-header--inner nocontent"> <div class="devsite-top-logo-row-wrapper-wrapper"> <div class="devsite-top-logo-row-wrapper"> <div class="devsite-top-logo-row"> <button type="button" id="devsite-hamburger-menu" class="devsite-header-icon-button button-flat material-icons gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Navigation menu button" visually-hidden aria-label="Open menu"> </button> <div class="devsite-product-name-wrapper"> <a href="/" class="devsite-site-logo-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Site logo" track-type="globalNav" track-name="androidDevelopers" track-metadata-position="nav" track-metadata-eventDetail="nav"> <picture> <source srcset="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/android/images/lockup-dark-theme.svg" media="(prefers-color-scheme: dark)" class="devsite-dark-theme" alt="Android Developers"> <img src="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/android/images/lockup.svg" class="devsite-site-logo" alt="Android Developers"> </picture> </a> <span class="devsite-product-name"> <ul class="devsite-breadcrumb-list" > <li class="devsite-breadcrumb-item "> </li> </ul> </span> </div> <div class="devsite-top-logo-row-middle"> <div class="devsite-header-upper-tabs"> <devsite-tabs class="upper-tabs"> <nav class="devsite-tabs-wrapper" aria-label="Upper tabs"> <tab class="devsite-dropdown devsite-dropdown-full "> <a href="https://developer.android.com/get-started" track-metadata-eventdetail="https://developer.android.com/get-started" class="devsite-tabs-content gc-analytics-event android-dropdown-tab" track-type="nav" track-metadata-position="nav - essentials" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Essentials" track-name="essentials" > Essentials </a> <a href="#" role="button" aria-haspopup="true" aria-expanded="false" aria-label="Dropdown menu for Essentials" track-type="nav" track-metadata-eventdetail="https://developer.android.com/get-started" track-metadata-position="nav - essentials" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Essentials" track-name="essentials" class="devsite-tabs-dropdown-toggle devsite-icon devsite-icon-arrow-drop-down"></a> <div class="devsite-tabs-dropdown" aria-label="submenu" hidden> <div class="devsite-tabs-dropdown-content"> <div class="devsite-tabs-dropdown-column android-dropdown android-dropdown-primary android-dropdown-studio"> <ul class="devsite-tabs-dropdown-section "> <li class="devsite-nav-title" role="heading" tooltip>Gemini in Android Studio</li> <li class="devsite-nav-description">Your AI development companion for Android development. </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/gemini-in-android" track-type="nav" track-metadata-eventdetail="https://developer.android.com/gemini-in-android" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="gemini in android studio" tooltip class="button button-primary" > <div class="devsite-nav-item-title"> Learn more </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/studio" track-type="nav" track-metadata-eventdetail="https://developer.android.com/studio" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="gemini in android studio" tooltip class="button button-white" > <div class="devsite-nav-item-title"> Get Android Studio </div> </a> </li> </ul> </div> <div class="devsite-tabs-dropdown-column android-dropdown"> <ul class="devsite-tabs-dropdown-section android-dropdown-section-icon android-dropdown-section-icon-launch"> <li class="devsite-nav-title" role="heading" tooltip>Get started</li> <li class="devsite-nav-description">Start by creating your first app. Go deeper with our training courses or explore app development on your own. </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/get-started/overview" track-type="nav" track-metadata-eventdetail="https://developer.android.com/get-started/overview" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="get started" tooltip > <div class="devsite-nav-item-title"> Hello world </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/courses" track-type="nav" track-metadata-eventdetail="https://developer.android.com/courses" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="get started" tooltip > <div class="devsite-nav-item-title"> Training courses </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/get-started/codelabs" track-type="nav" track-metadata-eventdetail="https://developer.android.com/get-started/codelabs" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="get started" tooltip > <div class="devsite-nav-item-title"> Tutorials </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/kotlin" track-type="nav" track-metadata-eventdetail="https://developer.android.com/kotlin" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="get started" tooltip > <div class="devsite-nav-item-title"> Kotlin for Android </div> </a> </li> <li class="devsite-nav-item"> <a href="https://play.google.com/console/about/guides/monetize/" track-type="nav" track-metadata-eventdetail="https://play.google.com/console/about/guides/monetize/" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="get started" tooltip > <div class="devsite-nav-item-title"> Monetization with Play ↗️ </div> </a> </li> </ul> </div> <div class="devsite-tabs-dropdown-column android-dropdown"> <ul class="devsite-tabs-dropdown-section android-dropdown-section-icon android-dropdown-section-icon-multiple-screens"> <li class="devsite-nav-title" role="heading" tooltip>Extend by device</li> <li class="devsite-nav-description">Build apps that give your users seamless experiences from phones to tablets, watches, and more. </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/adaptive-apps" track-type="nav" track-metadata-eventdetail="https://developer.android.com/adaptive-apps" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="extend by device" tooltip > <div class="devsite-nav-item-title"> Adaptive apps </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/wear" track-type="nav" track-metadata-eventdetail="https://developer.android.com/wear" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="extend by device" tooltip > <div class="devsite-nav-item-title"> Wear OS </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/cars" track-type="nav" track-metadata-eventdetail="https://developer.android.com/cars" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="extend by device" tooltip > <div class="devsite-nav-item-title"> Android for Cars </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/tv" track-type="nav" track-metadata-eventdetail="https://developer.android.com/tv" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="extend by device" tooltip > <div class="devsite-nav-item-title"> Android TV </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/chrome-os" track-type="nav" track-metadata-eventdetail="https://developer.android.com/chrome-os" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="extend by device" tooltip > <div class="devsite-nav-item-title"> ChromeOS </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/multi-device-development" track-type="nav" track-metadata-eventdetail="https://developer.android.com/multi-device-development" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="extend by device" tooltip > <div class="devsite-nav-item-title"> Cross-device SDK </div> </a> </li> </ul> </div> <div class="devsite-tabs-dropdown-column android-dropdown"> <ul class="devsite-tabs-dropdown-section android-dropdown-section-icon android-dropdown-section-icon-platform"> <li class="devsite-nav-title" role="heading" tooltip>Build by category</li> <li class="devsite-nav-description">Learn to build for your use case by following Google's prescriptive and opinionated guidance. </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/games" track-type="nav" track-metadata-eventdetail="https://developer.android.com/games" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="build by category" tooltip > <div class="devsite-nav-item-title"> Games </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/media" track-type="nav" track-metadata-eventdetail="https://developer.android.com/media" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="build by category" tooltip > <div class="devsite-nav-item-title"> Camera & Media </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/social-and-messaging" track-type="nav" track-metadata-eventdetail="https://developer.android.com/social-and-messaging" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="build by category" tooltip > <div class="devsite-nav-item-title"> Social & messaging </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/health-and-fitness" track-type="nav" track-metadata-eventdetail="https://developer.android.com/health-and-fitness" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="build by category" tooltip > <div class="devsite-nav-item-title"> Health & Fitness </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/productivity" track-type="nav" track-metadata-eventdetail="https://developer.android.com/productivity" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="build by category" tooltip > <div class="devsite-nav-item-title"> Productivity </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/work/overview" track-type="nav" track-metadata-eventdetail="https://developer.android.com/work/overview" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="build by category" tooltip > <div class="devsite-nav-item-title"> Enterprise apps </div> </a> </li> </ul> </div> <div class="devsite-tabs-dropdown-column android-dropdown"> <ul class="devsite-tabs-dropdown-section android-dropdown-section-icon android-dropdown-section-icon-stars"> <li class="devsite-nav-title" role="heading" tooltip>Get the latest</li> <li class="devsite-nav-description">Stay in touch with the latest releases throughout the year, join our preview programs, and give us your feedback. </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/latest-updates" track-type="nav" track-metadata-eventdetail="https://developer.android.com/latest-updates" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="get the latest" tooltip > <div class="devsite-nav-item-title"> Latest updates </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/latest-updates/experimental" track-type="nav" track-metadata-eventdetail="https://developer.android.com/latest-updates/experimental" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="get the latest" tooltip > <div class="devsite-nav-item-title"> Experimental updates </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/studio/preview" track-type="nav" track-metadata-eventdetail="https://developer.android.com/studio/preview" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="get the latest" tooltip > <div class="devsite-nav-item-title"> Android Studio preview </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/jetpack/androidx/versions" track-type="nav" track-metadata-eventdetail="https://developer.android.com/jetpack/androidx/versions" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="get the latest" tooltip > <div class="devsite-nav-item-title"> Jetpack & Compose libraries </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/training/wearables/versions/4" track-type="nav" track-metadata-eventdetail="https://developer.android.com/training/wearables/versions/4" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="get the latest" tooltip > <div class="devsite-nav-item-title"> Wear OS preview </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/design-for-safety/privacy-sandbox" track-type="nav" track-metadata-eventdetail="https://developer.android.com/design-for-safety/privacy-sandbox" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="get the latest" tooltip > <div class="devsite-nav-item-title"> Privacy Sandbox </div> </a> </li> </ul> </div> </div> </div> </tab> <tab class="devsite-dropdown devsite-dropdown-full "> <a href="https://developer.android.com/design" track-metadata-eventdetail="https://developer.android.com/design" class="devsite-tabs-content gc-analytics-event android-dropdown-tab" track-type="nav" track-metadata-position="nav - design & plan" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Design & Plan" track-name="design & plan" > Design & Plan </a> <a href="#" role="button" aria-haspopup="true" aria-expanded="false" aria-label="Dropdown menu for Design & Plan" track-type="nav" track-metadata-eventdetail="https://developer.android.com/design" track-metadata-position="nav - design & plan" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Design & Plan" track-name="design & plan" class="devsite-tabs-dropdown-toggle devsite-icon devsite-icon-arrow-drop-down"></a> <div class="devsite-tabs-dropdown" aria-label="submenu" hidden> <div class="devsite-tabs-dropdown-content"> <div class="devsite-tabs-dropdown-column android-dropdown"> <ul class="devsite-tabs-dropdown-section android-dropdown-section-icon android-dropdown-section-icon-layout"> <li class="devsite-nav-title" role="heading" tooltip>UI Design</li> <li class="devsite-nav-description">Design a beautiful user interface using Android best practices.</li> <li class="devsite-nav-item"> <a href="https://developer.android.com/design/ui" track-type="nav" track-metadata-eventdetail="https://developer.android.com/design/ui" track-metadata-position="nav - design & plan" track-metadata-module="tertiary nav" track-metadata-module_headline="ui design" tooltip > <div class="devsite-nav-item-title"> Design for Android </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/design/ui/mobile" track-type="nav" track-metadata-eventdetail="https://developer.android.com/design/ui/mobile" track-metadata-position="nav - design & plan" track-metadata-module="tertiary nav" track-metadata-module_headline="ui design" tooltip > <div class="devsite-nav-item-title"> Mobile </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/design/ui/large-screens" track-type="nav" track-metadata-eventdetail="https://developer.android.com/design/ui/large-screens" track-metadata-position="nav - design & plan" track-metadata-module="tertiary nav" track-metadata-module_headline="ui design" tooltip > <div class="devsite-nav-item-title"> Large screens (e.g., tablets) </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/design/ui/widget" track-type="nav" track-metadata-eventdetail="https://developer.android.com/design/ui/widget" track-metadata-position="nav - design & plan" track-metadata-module="tertiary nav" track-metadata-module_headline="ui design" tooltip > <div class="devsite-nav-item-title"> Widgets </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/design/ui/wear" track-type="nav" track-metadata-eventdetail="https://developer.android.com/design/ui/wear" track-metadata-position="nav - design & plan" track-metadata-module="tertiary nav" track-metadata-module_headline="ui design" tooltip > <div class="devsite-nav-item-title"> Wear OS </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/design/ui/tv" track-type="nav" track-metadata-eventdetail="https://developer.android.com/design/ui/tv" track-metadata-position="nav - design & plan" track-metadata-module="tertiary nav" track-metadata-module_headline="ui design" tooltip > <div class="devsite-nav-item-title"> Android TV </div> </a> </li> </ul> </div> <div class="devsite-tabs-dropdown-column android-dropdown"> <ul class="devsite-tabs-dropdown-section android-dropdown-section-icon android-dropdown-section-icon-design"> <li class="devsite-nav-title" role="heading" tooltip>Architecture</li> <li class="devsite-nav-description">Design robust, testable, and maintainable app logic and services.</li> <li class="devsite-nav-item"> <a href="https://developer.android.com/topic/architecture/intro" track-type="nav" track-metadata-eventdetail="https://developer.android.com/topic/architecture/intro" track-metadata-position="nav - design & plan" track-metadata-module="tertiary nav" track-metadata-module_headline="architecture" tooltip > <div class="devsite-nav-item-title"> Introduction </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/topic/libraries/view-binding" track-type="nav" track-metadata-eventdetail="https://developer.android.com/topic/libraries/view-binding" track-metadata-position="nav - design & plan" track-metadata-module="tertiary nav" track-metadata-module_headline="architecture" tooltip > <div class="devsite-nav-item-title"> Libraries </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/guide/navigation/navigation-principles" track-type="nav" track-metadata-eventdetail="https://developer.android.com/guide/navigation/navigation-principles" track-metadata-position="nav - design & plan" track-metadata-module="tertiary nav" track-metadata-module_headline="architecture" tooltip > <div class="devsite-nav-item-title"> Navigation </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/topic/modularization" track-type="nav" track-metadata-eventdetail="https://developer.android.com/topic/modularization" track-metadata-position="nav - design & plan" track-metadata-module="tertiary nav" track-metadata-module_headline="architecture" tooltip > <div class="devsite-nav-item-title"> Modularization </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/training/testing/fundamentals" track-type="nav" track-metadata-eventdetail="https://developer.android.com/training/testing/fundamentals" track-metadata-position="nav - design & plan" track-metadata-module="tertiary nav" track-metadata-module_headline="architecture" tooltip > <div class="devsite-nav-item-title"> Testing </div> </a> </li> </ul> </div> <div class="devsite-tabs-dropdown-column android-dropdown"> <ul class="devsite-tabs-dropdown-section android-dropdown-section-icon android-dropdown-section-icon-vitals"> <li class="devsite-nav-title" role="heading" tooltip>Quality</li> <li class="devsite-nav-description">Plan for app quality and align with Play store guidelines.</li> <li class="devsite-nav-item"> <a href="https://developer.android.com/quality" track-type="nav" track-metadata-eventdetail="https://developer.android.com/quality" track-metadata-position="nav - design & plan" track-metadata-module="tertiary nav" track-metadata-module_headline="quality" tooltip > <div class="devsite-nav-item-title"> Overview </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/quality/core-value" track-type="nav" track-metadata-eventdetail="https://developer.android.com/quality/core-value" track-metadata-position="nav - design & plan" track-metadata-module="tertiary nav" track-metadata-module_headline="quality" tooltip > <div class="devsite-nav-item-title"> Core value </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/quality/user-experience" track-type="nav" track-metadata-eventdetail="https://developer.android.com/quality/user-experience" track-metadata-position="nav - design & plan" track-metadata-module="tertiary nav" track-metadata-module_headline="quality" tooltip > <div class="devsite-nav-item-title"> User experience </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/quality/technical" track-type="nav" track-metadata-eventdetail="https://developer.android.com/quality/technical" track-metadata-position="nav - design & plan" track-metadata-module="tertiary nav" track-metadata-module_headline="quality" tooltip > <div class="devsite-nav-item-title"> Technical quality </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/quality/privacy-and-security" track-type="nav" track-metadata-eventdetail="https://developer.android.com/quality/privacy-and-security" track-metadata-position="nav - design & plan" track-metadata-module="tertiary nav" track-metadata-module_headline="quality" tooltip > <div class="devsite-nav-item-title"> Security </div> </a> </li> </ul> </div> <div class="devsite-tabs-dropdown-column android-dropdown"> <ul class="devsite-tabs-dropdown-section android-dropdown-section-icon android-dropdown-section-icon-security-2"> <li class="devsite-nav-title" role="heading" tooltip>Security</li> <li class="devsite-nav-description">Safeguard users against threats and ensure a secure Android experience.</li> <li class="devsite-nav-item"> <a href="https://developer.android.com/security" track-type="nav" track-metadata-eventdetail="https://developer.android.com/security" track-metadata-position="nav - design & plan" track-metadata-module="tertiary nav" track-metadata-module_headline="security" tooltip > <div class="devsite-nav-item-title"> Overview </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/privacy-and-security/about" track-type="nav" track-metadata-eventdetail="https://developer.android.com/privacy-and-security/about" track-metadata-position="nav - design & plan" track-metadata-module="tertiary nav" track-metadata-module_headline="security" tooltip > <div class="devsite-nav-item-title"> Privacy </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/identity" track-type="nav" track-metadata-eventdetail="https://developer.android.com/identity" track-metadata-position="nav - design & plan" track-metadata-module="tertiary nav" track-metadata-module_headline="security" tooltip > <div class="devsite-nav-item-title"> Identity </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/security/fraud-prevention" track-type="nav" track-metadata-eventdetail="https://developer.android.com/security/fraud-prevention" track-metadata-position="nav - design & plan" track-metadata-module="tertiary nav" track-metadata-module_headline="security" tooltip > <div class="devsite-nav-item-title"> Fraud prevention </div> </a> </li> </ul> </div> <div class="devsite-tabs-dropdown-column android-dropdown"> <ul class="devsite-tabs-dropdown-section android-dropdown-section-icon android-dropdown-section-icon-earth"> <li class="devsite-nav-title" role="heading" tooltip>Build for Billions</li> <li class="devsite-nav-description">Create the best experience for entry-level devices</li> <li class="devsite-nav-item"> <a href="https://developer.android.com/build-for-billions" track-type="nav" track-metadata-eventdetail="https://developer.android.com/build-for-billions" track-metadata-position="nav - design & plan" track-metadata-module="tertiary nav" track-metadata-module_headline="build for billions" tooltip > <div class="devsite-nav-item-title"> Overview </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/docs/quality-guidelines/build-for-billions" track-type="nav" track-metadata-eventdetail="https://developer.android.com/docs/quality-guidelines/build-for-billions" track-metadata-position="nav - design & plan" track-metadata-module="tertiary nav" track-metadata-module_headline="build for billions" tooltip > <div class="devsite-nav-item-title"> About new markets </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/guide/topics/androidgo" track-type="nav" track-metadata-eventdetail="https://developer.android.com/guide/topics/androidgo" track-metadata-position="nav - design & plan" track-metadata-module="tertiary nav" track-metadata-module_headline="build for billions" tooltip > <div class="devsite-nav-item-title"> Android (Go edition) </div> </a> </li> </ul> </div> </div> </div> </tab> <tab class="devsite-dropdown devsite-dropdown-full devsite-active "> <a href="https://developer.android.com/develop" track-metadata-eventdetail="https://developer.android.com/develop" class="devsite-tabs-content gc-analytics-event android-dropdown-tab" track-type="nav" track-metadata-position="nav - develop" track-metadata-module="primary nav" aria-label="Develop, selected" data-category="Site-Wide Custom Events" data-label="Tab: Develop" track-name="develop" > Develop </a> <a href="#" role="button" aria-haspopup="true" aria-expanded="false" aria-label="Dropdown menu for Develop" track-type="nav" track-metadata-eventdetail="https://developer.android.com/develop" track-metadata-position="nav - develop" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Develop" track-name="develop" class="devsite-tabs-dropdown-toggle devsite-icon devsite-icon-arrow-drop-down"></a> <div class="devsite-tabs-dropdown" aria-label="submenu" hidden> <div class="devsite-tabs-dropdown-content"> <div class="devsite-tabs-dropdown-column android-dropdown android-dropdown-primary android-dropdown-ai"> <ul class="devsite-tabs-dropdown-section "> <li class="devsite-nav-title" role="heading" tooltip>Build AI experiences</li> <li class="devsite-nav-description">Build AI-powered Android apps with Gemini APIs and more. </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/ai" track-type="nav" track-metadata-eventdetail="https://developer.android.com/ai" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="build ai experiences" tooltip class="button button-primary" > <div class="devsite-nav-item-title"> Get started </div> </a> </li> </ul> </div> <div class="devsite-tabs-dropdown-column android-dropdown"> <ul class="devsite-tabs-dropdown-section android-dropdown-section-icon android-dropdown-section-icon-flag"> <li class="devsite-nav-title" role="heading" tooltip>Core areas</li> <li class="devsite-nav-description">Get the samples and docs for the features you need.</li> <li class="devsite-nav-item"> <a href="https://developer.android.com/samples" track-type="nav" track-metadata-eventdetail="https://developer.android.com/samples" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="core areas" tooltip > <div class="devsite-nav-item-title"> Samples </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/quick-guides" track-type="nav" track-metadata-eventdetail="https://developer.android.com/quick-guides" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="core areas" tooltip > <div class="devsite-nav-item-title"> Try Quick Guidesᵇᵉᵗᵃ </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/develop/ui" track-type="nav" track-metadata-eventdetail="https://developer.android.com/develop/ui" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="core areas" tooltip > <div class="devsite-nav-item-title"> User interfaces </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/guide/topics/permissions/overview" track-type="nav" track-metadata-eventdetail="https://developer.android.com/guide/topics/permissions/overview" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="core areas" tooltip > <div class="devsite-nav-item-title"> Permissions </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/develop/background-work" track-type="nav" track-metadata-eventdetail="https://developer.android.com/develop/background-work" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="core areas" tooltip > <div class="devsite-nav-item-title"> Background work </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/guide/topics/data" track-type="nav" track-metadata-eventdetail="https://developer.android.com/guide/topics/data" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="core areas" tooltip > <div class="devsite-nav-item-title"> Data and files </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/develop#core-areas" track-type="nav" track-metadata-eventdetail="https://developer.android.com/develop#core-areas" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="core areas" tooltip > <div class="devsite-nav-item-title"> All core areas ⤵️ </div> </a> </li> </ul> </div> <div class="devsite-tabs-dropdown-column android-dropdown"> <ul class="devsite-tabs-dropdown-section android-dropdown-section-icon android-dropdown-section-icon-tools-2"> <li class="devsite-nav-title" role="heading" tooltip>Tools and workflow</li> <li class="devsite-nav-description">Use the IDE to write and build your app, or create your own pipeline.</li> <li class="devsite-nav-item"> <a href="https://developer.android.com/studio/write" track-type="nav" track-metadata-eventdetail="https://developer.android.com/studio/write" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="tools and workflow" tooltip > <div class="devsite-nav-item-title"> Write and debug code </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/build/gradle-build-overview" track-type="nav" track-metadata-eventdetail="https://developer.android.com/build/gradle-build-overview" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="tools and workflow" tooltip > <div class="devsite-nav-item-title"> Build projects </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/training/testing" track-type="nav" track-metadata-eventdetail="https://developer.android.com/training/testing" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="tools and workflow" tooltip > <div class="devsite-nav-item-title"> Test your app </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/topic/performance/overview" track-type="nav" track-metadata-eventdetail="https://developer.android.com/topic/performance/overview" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="tools and workflow" tooltip > <div class="devsite-nav-item-title"> Performance </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/tools" track-type="nav" track-metadata-eventdetail="https://developer.android.com/tools" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="tools and workflow" tooltip > <div class="devsite-nav-item-title"> Command-line tools </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/reference/tools/gradle-api" track-type="nav" track-metadata-eventdetail="https://developer.android.com/reference/tools/gradle-api" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="tools and workflow" tooltip > <div class="devsite-nav-item-title"> Gradle plugin API </div> </a> </li> </ul> </div> <div class="devsite-tabs-dropdown-column android-dropdown"> <ul class="devsite-tabs-dropdown-section android-dropdown-section-icon android-dropdown-section-icon-multiple-screens"> <li class="devsite-nav-title" role="heading" tooltip>Device tech</li> <li class="devsite-nav-description">Write code for form factors. Connect devices and share data.</li> <li class="devsite-nav-item"> <a href="https://developer.android.com/guide/topics/large-screens/get-started-with-large-screens" track-type="nav" track-metadata-eventdetail="https://developer.android.com/guide/topics/large-screens/get-started-with-large-screens" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="device tech" tooltip > <div class="devsite-nav-item-title"> Large screens (e.g., tablets) </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/training/wearables" track-type="nav" track-metadata-eventdetail="https://developer.android.com/training/wearables" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="device tech" tooltip > <div class="devsite-nav-item-title"> Wear OS </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/health-and-fitness/guides" track-type="nav" track-metadata-eventdetail="https://developer.android.com/health-and-fitness/guides" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="device tech" tooltip > <div class="devsite-nav-item-title"> Android Health </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/guide/topics/connectivity/cross-device-sdk/overview" track-type="nav" track-metadata-eventdetail="https://developer.android.com/guide/topics/connectivity/cross-device-sdk/overview" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="device tech" tooltip > <div class="devsite-nav-item-title"> Cross-device SDK </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/training/cars" track-type="nav" track-metadata-eventdetail="https://developer.android.com/training/cars" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="device tech" tooltip > <div class="devsite-nav-item-title"> Android for Cars </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/training/tv" track-type="nav" track-metadata-eventdetail="https://developer.android.com/training/tv" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="device tech" tooltip > <div class="devsite-nav-item-title"> Android TV </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/chrome-os/intro" track-type="nav" track-metadata-eventdetail="https://developer.android.com/chrome-os/intro" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="device tech" tooltip > <div class="devsite-nav-item-title"> ChromeOS </div> </a> </li> </ul> </div> <div class="devsite-tabs-dropdown-column android-dropdown"> <ul class="devsite-tabs-dropdown-section android-dropdown-section-icon android-dropdown-section-icon-core-library"> <li class="devsite-nav-title" role="heading" tooltip>Libraries</li> <li class="devsite-nav-description">Browse API reference documentation with all the details.</li> <li class="devsite-nav-item"> <a href="https://developer.android.com/reference/packages" track-type="nav" track-metadata-eventdetail="https://developer.android.com/reference/packages" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="libraries" tooltip > <div class="devsite-nav-item-title"> Android platform </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/jetpack/androidx/explorer" track-type="nav" track-metadata-eventdetail="https://developer.android.com/jetpack/androidx/explorer" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="libraries" tooltip > <div class="devsite-nav-item-title"> Jetpack libraries </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/jetpack/androidx/releases/compose" track-type="nav" track-metadata-eventdetail="https://developer.android.com/jetpack/androidx/releases/compose" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="libraries" tooltip > <div class="devsite-nav-item-title"> Compose libraries </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developers.google.com/android/reference/packages" track-type="nav" track-metadata-eventdetail="https://developers.google.com/android/reference/packages" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="libraries" tooltip > <div class="devsite-nav-item-title"> Google Play services ↗️ </div> </a> </li> <li class="devsite-nav-item"> <a href="https://play.google.com/sdks" track-type="nav" track-metadata-eventdetail="https://play.google.com/sdks" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="libraries" tooltip > <div class="devsite-nav-item-title"> Google Play SDK index ↗️ </div> </a> </li> </ul> </div> </div> </div> </tab> <tab > <a href="https://developer.android.com/distribute" track-metadata-eventdetail="https://developer.android.com/distribute" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - google play" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Google Play" track-name="google play" > Google Play </a> </tab> <tab > <a href="https://developer.android.com/community" track-metadata-eventdetail="https://developer.android.com/community" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - community" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Community" track-name="community" > Community </a> </tab> </nav> </devsite-tabs> </div> <devsite-search enable-signin enable-search enable-suggestions enable-query-completion project-name="Jetpack Compose" tenant-name="Android Developers" > <form class="devsite-search-form" action="https://developer.android.com/s/results" method="GET"> <div class="devsite-search-container"> <button type="button" search-open class="devsite-search-button devsite-header-icon-button button-flat material-icons" aria-label="Open search"></button> <div class="devsite-searchbox"> <input aria-activedescendant="" aria-autocomplete="list" aria-label="Search" aria-expanded="false" aria-haspopup="listbox" autocomplete="off" class="devsite-search-field devsite-search-query" name="q" placeholder="Search" role="combobox" type="text" value="" > <div class="devsite-search-image material-icons" aria-hidden="true"> </div> <div class="devsite-search-shortcut-icon-container" aria-hidden="true"> <kbd class="devsite-search-shortcut-icon">/</kbd> </div> </div> </div> </form> <button type="button" search-close class="devsite-search-button devsite-header-icon-button button-flat material-icons" aria-label="Close search"></button> </devsite-search> </div> <devsite-appearance-selector></devsite-appearance-selector> <devsite-language-selector> <ul role="presentation"> <li role="presentation"> <a role="menuitem" lang="en" >English</a> </li> <li role="presentation"> <a role="menuitem" lang="de" >Deutsch</a> </li> <li role="presentation"> <a role="menuitem" lang="es_419" >Español – América Latina</a> </li> <li role="presentation"> <a role="menuitem" lang="fr" >Français</a> </li> <li role="presentation"> <a role="menuitem" lang="id" >Indonesia</a> </li> <li role="presentation"> <a role="menuitem" lang="it" >Italiano</a> </li> <li role="presentation"> <a role="menuitem" lang="pl" >Polski</a> </li> <li role="presentation"> <a role="menuitem" lang="pt_br" >Português – Brasil</a> </li> <li role="presentation"> <a role="menuitem" lang="vi" >Tiếng Việt</a> </li> <li role="presentation"> <a role="menuitem" lang="tr" >Türkçe</a> </li> <li role="presentation"> <a role="menuitem" lang="ru" >Русский</a> </li> <li role="presentation"> <a role="menuitem" lang="he" >עברית</a> </li> <li role="presentation"> <a role="menuitem" lang="ar" >العربيّة</a> </li> <li role="presentation"> <a role="menuitem" lang="fa" >فارسی</a> </li> <li role="presentation"> <a role="menuitem" lang="hi" >हिंदी</a> </li> <li role="presentation"> <a role="menuitem" lang="bn" >বাংলা</a> </li> <li role="presentation"> <a role="menuitem" lang="th" >ภาษาไทย</a> </li> <li role="presentation"> <a role="menuitem" lang="zh_cn" >中文 – 简体</a> </li> <li role="presentation"> <a role="menuitem" lang="zh_tw" >中文 – 繁體</a> </li> <li role="presentation"> <a role="menuitem" lang="ja" >日本語</a> </li> <li role="presentation"> <a role="menuitem" lang="ko" >한국어</a> </li> </ul> </devsite-language-selector> <a class="devsite-header-link devsite-top-button button gc-analytics-event" href="https://developer.android.com/studio" data-category="Site-Wide Custom Events" data-label="Site header link" > Android Studio </a> <devsite-user enable-profiles id="devsite-user"> <span class="button devsite-top-button" aria-hidden="true" visually-hidden>Sign in</span> </devsite-user> </div> </div> </div> <div class="devsite-collapsible-section "> <div class="devsite-header-background"> <div class="devsite-product-id-row" > <div class="devsite-product-description-row"> <ul class="devsite-breadcrumb-list" aria-label="Lower header breadcrumb"> <li class="devsite-breadcrumb-item "> <a href="https://developer.android.com/develop/core-areas" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Lower Header" data-value="1" track-type="globalNav" track-name="breadcrumb" track-metadata-position="1" track-metadata-eventdetail="Core areas" > Core areas </a> </li> <li class="devsite-breadcrumb-item "> <div class="devsite-breadcrumb-guillemet material-icons" aria-hidden="true"></div> <a href="https://developer.android.com/develop/ui" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Lower Header" data-value="2" track-type="globalNav" track-name="breadcrumb" track-metadata-position="2" track-metadata-eventdetail="Jetpack Compose" > UI </a> </li> </ul> </div> </div> <div class="devsite-doc-set-nav-row"> <devsite-tabs class="lower-tabs"> <nav class="devsite-tabs-wrapper" aria-label="Lower tabs"> <tab > <a href="https://developer.android.com/develop/ui" track-metadata-eventdetail="https://developer.android.com/develop/ui" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - overview" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Overview" track-name="overview" > Overview </a> </tab> <tab class="devsite-active"> <a href="https://developer.android.com/develop/ui/compose/tutorial" track-metadata-eventdetail="https://developer.android.com/develop/ui/compose/tutorial" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - tutorial" track-metadata-module="primary nav" aria-label="Tutorial, selected" data-category="Site-Wide Custom Events" data-label="Tab: Tutorial" track-name="tutorial" > Tutorial </a> </tab> <tab > <a href="https://developer.android.com/develop/ui/compose/samples" track-metadata-eventdetail="https://developer.android.com/develop/ui/compose/samples" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - samples" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Samples" track-name="samples" > Samples </a> </tab> <tab > <a href="https://developer.android.com/develop/ui/compose/documentation" track-metadata-eventdetail="https://developer.android.com/develop/ui/compose/documentation" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - guides" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Guides" track-name="guides" > Guides </a> </tab> <tab > <a href="https://developer.android.com/quick-guides" track-metadata-eventdetail="https://developer.android.com/quick-guides" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - try quick guides ➡️" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Try Quick Guides ➡️" track-name="try quick guides ➡️" > Try Quick Guides ➡️ </a> </tab> </nav> </devsite-tabs> </div> </div> </div> </div> </devsite-header> <devsite-book-nav scrollbars hidden> <div class="devsite-book-nav-filter" hidden> <span class="filter-list-icon material-icons" aria-hidden="true"></span> <input type="text" placeholder="Filter" aria-label="Type to filter" role="searchbox"> <span class="filter-clear-button hidden" data-title="Clear filter" aria-label="Clear filter" role="button" tabindex="0"></span> </div> <nav class="devsite-book-nav devsite-nav nocontent" aria-label="Side menu"> <div class="devsite-mobile-header"> <button type="button" id="devsite-close-nav" class="devsite-header-icon-button button-flat material-icons gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Close navigation" aria-label="Close navigation"> </button> <div class="devsite-product-name-wrapper"> <a href="/" class="devsite-site-logo-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Site logo" track-type="globalNav" track-name="androidDevelopers" track-metadata-position="nav" track-metadata-eventDetail="nav"> <picture> <source srcset="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/android/images/lockup-dark-theme.svg" media="(prefers-color-scheme: dark)" class="devsite-dark-theme" alt="Android Developers"> <img src="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/android/images/lockup.svg" class="devsite-site-logo" alt="Android Developers"> </picture> </a> <span class="devsite-product-name"> <ul class="devsite-breadcrumb-list" > <li class="devsite-breadcrumb-item "> </li> </ul> </span> </div> </div> <div class="devsite-book-nav-wrapper"> <div class="devsite-mobile-nav-top"> <ul class="devsite-nav-list"> <li class="devsite-nav-item"> <a href="/get-started" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: Essentials" track-name="essentials" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Essentials" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Essentials </span> </a> <ul class="devsite-nav-responsive-tabs devsite-nav-has-menu "> <li class="devsite-nav-item"> <span class="devsite-nav-title" tooltip data-category="Site-Wide Custom Events" data-label="Tab: Essentials" track-name="essentials" > <span class="devsite-nav-text" tooltip menu="Essentials"> More </span> <span class="devsite-nav-icon material-icons" data-icon="forward" menu="Essentials"> </span> </span> </li> </ul> </li> <li class="devsite-nav-item"> <a href="/design" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: Design & Plan" track-name="design & plan" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Design & Plan" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Design & Plan </span> </a> <ul class="devsite-nav-responsive-tabs devsite-nav-has-menu "> <li class="devsite-nav-item"> <span class="devsite-nav-title" tooltip data-category="Site-Wide Custom Events" data-label="Tab: Design & Plan" track-name="design & plan" > <span class="devsite-nav-text" tooltip menu="Design & Plan"> More </span> <span class="devsite-nav-icon material-icons" data-icon="forward" menu="Design & Plan"> </span> </span> </li> </ul> </li> <li class="devsite-nav-item"> <a href="/develop" class="devsite-nav-title gc-analytics-event devsite-nav-active" data-category="Site-Wide Custom Events" data-label="Tab: Develop" track-name="develop" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Develop" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Develop </span> </a> <ul class="devsite-nav-responsive-tabs devsite-nav-has-menu "> <li class="devsite-nav-item"> <span class="devsite-nav-title" tooltip data-category="Site-Wide Custom Events" data-label="Tab: Develop" track-name="develop" > <span class="devsite-nav-text" tooltip menu="Develop"> More </span> <span class="devsite-nav-icon material-icons" data-icon="forward" menu="Develop"> </span> </span> </li> </ul> <ul class="devsite-nav-responsive-tabs"> <li class="devsite-nav-item"> <a href="/develop/ui" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: Overview" track-name="overview" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Overview" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Overview </span> </a> </li> <li class="devsite-nav-item"> <a href="/develop/ui/compose/tutorial" class="devsite-nav-title gc-analytics-event devsite-nav-active" data-category="Site-Wide Custom Events" data-label="Tab: Tutorial" track-name="tutorial" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Tutorial" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Tutorial </span> </a> </li> <li class="devsite-nav-item"> <a href="/develop/ui/compose/samples" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: Samples" track-name="samples" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Samples" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Samples </span> </a> </li> <li class="devsite-nav-item"> <a href="/develop/ui/compose/documentation" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Guides" track-name="guides" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Guides" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Guides </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/quick-guides" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: Try Quick Guides ➡️" track-name="try quick guides ➡️" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Try Quick Guides ➡️" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Try Quick Guides ➡️ </span> </a> </li> </ul> </li> <li class="devsite-nav-item"> <a href="/distribute" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: Google Play" track-name="google play" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Google Play" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Google Play </span> </a> </li> <li class="devsite-nav-item"> <a href="/community" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: Community" track-name="community" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Community" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Community </span> </a> </li> <li class="devsite-nav-item"> <a href="/studio" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Android Studio" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Android Studio </span> </a> </li> </ul> </div> <div class="devsite-mobile-nav-bottom"> <ul class="devsite-nav-list" menu="Essentials" aria-label="Side menu" hidden> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > Gemini in Android Studio </span> </span> </li> <li class="devsite-nav-item"> <a href="/gemini-in-android" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Learn more" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Learn more </span> </a> </li> <li class="devsite-nav-item"> <a href="/studio" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Get Android Studio" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Get Android Studio </span> </a> </li> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > Get started </span> </span> </li> <li class="devsite-nav-item"> <a href="/get-started/overview" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Hello world" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Hello world </span> </a> </li> <li class="devsite-nav-item"> <a href="/courses" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Training courses" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Training courses </span> </a> </li> <li class="devsite-nav-item"> <a href="/get-started/codelabs" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Tutorials" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Tutorials </span> </a> </li> <li class="devsite-nav-item"> <a href="/kotlin" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Kotlin for Android" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Kotlin for Android </span> </a> </li> <li class="devsite-nav-item"> <a href="https://play.google.com/console/about/guides/monetize/" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Monetization with Play ↗️" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Monetization with Play ↗️ </span> </a> </li> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > Extend by device </span> </span> </li> <li class="devsite-nav-item"> <a href="/adaptive-apps" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Adaptive apps" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Adaptive apps </span> </a> </li> <li class="devsite-nav-item"> <a href="/wear" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Wear OS" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Wear OS </span> </a> </li> <li class="devsite-nav-item"> <a href="/cars" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Android for Cars" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Android for Cars </span> </a> </li> <li class="devsite-nav-item"> <a href="/tv" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Android TV" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Android TV </span> </a> </li> <li class="devsite-nav-item"> <a href="/chrome-os" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: ChromeOS" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > ChromeOS </span> </a> </li> <li class="devsite-nav-item"> <a href="/multi-device-development" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Cross-device SDK" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Cross-device SDK </span> </a> </li> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > Build by category </span> </span> </li> <li class="devsite-nav-item"> <a href="/games" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Games" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Games </span> </a> </li> <li class="devsite-nav-item"> <a href="/media" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Camera & Media" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Camera & Media </span> </a> </li> <li class="devsite-nav-item"> <a href="/social-and-messaging" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Social & messaging" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Social & messaging </span> </a> </li> <li class="devsite-nav-item"> <a href="/health-and-fitness" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Health & Fitness" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Health & Fitness </span> </a> </li> <li class="devsite-nav-item"> <a href="/productivity" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Productivity" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Productivity </span> </a> </li> <li class="devsite-nav-item"> <a href="/work/overview" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Enterprise apps" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Enterprise apps </span> </a> </li> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > Get the latest </span> </span> </li> <li class="devsite-nav-item"> <a href="/latest-updates" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Latest updates" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Latest updates </span> </a> </li> <li class="devsite-nav-item"> <a href="/latest-updates/experimental" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Experimental updates" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Experimental updates </span> </a> </li> <li class="devsite-nav-item"> <a href="/studio/preview" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Android Studio preview" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Android Studio preview </span> </a> </li> <li class="devsite-nav-item"> <a href="/jetpack/androidx/versions" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Jetpack & Compose libraries" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Jetpack & Compose libraries </span> </a> </li> <li class="devsite-nav-item"> <a href="/training/wearables/versions/4" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Wear OS preview" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Wear OS preview </span> </a> </li> <li class="devsite-nav-item"> <a href="/design-for-safety/privacy-sandbox" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Privacy Sandbox" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Privacy Sandbox </span> </a> </li> </ul> <ul class="devsite-nav-list" menu="Design & Plan" aria-label="Side menu" hidden> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > UI Design </span> </span> </li> <li class="devsite-nav-item"> <a href="/design/ui" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Design for Android" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Design for Android </span> </a> </li> <li class="devsite-nav-item"> <a href="/design/ui/mobile" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Mobile" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Mobile </span> </a> </li> <li class="devsite-nav-item"> <a href="/design/ui/large-screens" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Large screens (e.g., tablets)" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Large screens (e.g., tablets) </span> </a> </li> <li class="devsite-nav-item"> <a href="/design/ui/widget" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Widgets" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Widgets </span> </a> </li> <li class="devsite-nav-item"> <a href="/design/ui/wear" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Wear OS" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Wear OS </span> </a> </li> <li class="devsite-nav-item"> <a href="/design/ui/tv" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Android TV" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Android TV </span> </a> </li> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > Architecture </span> </span> </li> <li class="devsite-nav-item"> <a href="/topic/architecture/intro" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Introduction" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Introduction </span> </a> </li> <li class="devsite-nav-item"> <a href="/topic/libraries/view-binding" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Libraries" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Libraries </span> </a> </li> <li class="devsite-nav-item"> <a href="/guide/navigation/navigation-principles" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Navigation" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Navigation </span> </a> </li> <li class="devsite-nav-item"> <a href="/topic/modularization" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Modularization" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Modularization </span> </a> </li> <li class="devsite-nav-item"> <a href="/training/testing/fundamentals" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Testing" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Testing </span> </a> </li> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > Quality </span> </span> </li> <li class="devsite-nav-item"> <a href="/quality" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Overview" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Overview </span> </a> </li> <li class="devsite-nav-item"> <a href="/quality/core-value" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Core value" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Core value </span> </a> </li> <li class="devsite-nav-item"> <a href="/quality/user-experience" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: User experience" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > User experience </span> </a> </li> <li class="devsite-nav-item"> <a href="/quality/technical" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Technical quality" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Technical quality </span> </a> </li> <li class="devsite-nav-item"> <a href="/quality/privacy-and-security" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Security" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Security </span> </a> </li> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > Security </span> </span> </li> <li class="devsite-nav-item"> <a href="/security" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Overview" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Overview </span> </a> </li> <li class="devsite-nav-item"> <a href="/privacy-and-security/about" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Privacy" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Privacy </span> </a> </li> <li class="devsite-nav-item"> <a href="/identity" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Identity" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Identity </span> </a> </li> <li class="devsite-nav-item"> <a href="/security/fraud-prevention" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Fraud prevention" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Fraud prevention </span> </a> </li> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > Build for Billions </span> </span> </li> <li class="devsite-nav-item"> <a href="/build-for-billions" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Overview" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Overview </span> </a> </li> <li class="devsite-nav-item"> <a href="/docs/quality-guidelines/build-for-billions" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: About new markets" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > About new markets </span> </a> </li> <li class="devsite-nav-item"> <a href="/guide/topics/androidgo" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Android (Go edition)" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Android (Go edition) </span> </a> </li> </ul> <ul class="devsite-nav-list" menu="Develop" aria-label="Side menu" hidden> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > Build AI experiences </span> </span> </li> <li class="devsite-nav-item"> <a href="/ai" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Get started" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Get started </span> </a> </li> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > Core areas </span> </span> </li> <li class="devsite-nav-item"> <a href="/samples" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Samples" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Samples </span> </a> </li> <li class="devsite-nav-item"> <a href="/quick-guides" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Try Quick Guidesᵇᵉᵗᵃ" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Try Quick Guidesᵇᵉᵗᵃ </span> </a> </li> <li class="devsite-nav-item"> <a href="/develop/ui" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: User interfaces" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > User interfaces </span> </a> </li> <li class="devsite-nav-item"> <a href="/guide/topics/permissions/overview" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Permissions" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Permissions </span> </a> </li> <li class="devsite-nav-item"> <a href="/develop/background-work" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Background work" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Background work </span> </a> </li> <li class="devsite-nav-item"> <a href="/guide/topics/data" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Data and files" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Data and files </span> </a> </li> <li class="devsite-nav-item"> <a href="/develop#core-areas" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: All core areas ⤵️" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > All core areas ⤵️ </span> </a> </li> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > Tools and workflow </span> </span> </li> <li class="devsite-nav-item"> <a href="/studio/write" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Write and debug code" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Write and debug code </span> </a> </li> <li class="devsite-nav-item"> <a href="/build/gradle-build-overview" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Build projects" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Build projects </span> </a> </li> <li class="devsite-nav-item"> <a href="/training/testing" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Test your app" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Test your app </span> </a> </li> <li class="devsite-nav-item"> <a href="/topic/performance/overview" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Performance" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Performance </span> </a> </li> <li class="devsite-nav-item"> <a href="/tools" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Command-line tools" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Command-line tools </span> </a> </li> <li class="devsite-nav-item"> <a href="/reference/tools/gradle-api" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Gradle plugin API" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Gradle plugin API </span> </a> </li> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > Device tech </span> </span> </li> <li class="devsite-nav-item"> <a href="/guide/topics/large-screens/get-started-with-large-screens" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Large screens (e.g., tablets)" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Large screens (e.g., tablets) </span> </a> </li> <li class="devsite-nav-item"> <a href="/training/wearables" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Wear OS" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Wear OS </span> </a> </li> <li class="devsite-nav-item"> <a href="/health-and-fitness/guides" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Android Health" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Android Health </span> </a> </li> <li class="devsite-nav-item"> <a href="/guide/topics/connectivity/cross-device-sdk/overview" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Cross-device SDK" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Cross-device SDK </span> </a> </li> <li class="devsite-nav-item"> <a href="/training/cars" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Android for Cars" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Android for Cars </span> </a> </li> <li class="devsite-nav-item"> <a href="/training/tv" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Android TV" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Android TV </span> </a> </li> <li class="devsite-nav-item"> <a href="/chrome-os/intro" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: ChromeOS" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > ChromeOS </span> </a> </li> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > Libraries </span> </span> </li> <li class="devsite-nav-item"> <a href="/reference/packages" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Android platform" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Android platform </span> </a> </li> <li class="devsite-nav-item"> <a href="/jetpack/androidx/explorer" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Jetpack libraries" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Jetpack libraries </span> </a> </li> <li class="devsite-nav-item"> <a href="/jetpack/androidx/releases/compose" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Compose libraries" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Compose libraries </span> </a> </li> <li class="devsite-nav-item"> <a href="https://developers.google.com/android/reference/packages" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Google Play services ↗️" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Google Play services ↗️ </span> </a> </li> <li class="devsite-nav-item"> <a href="https://play.google.com/sdks" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Google Play SDK index ↗️" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Google Play SDK index ↗️ </span> </a> </li> </ul> </div> </div> </nav> </devsite-book-nav> <section id="gc-wrapper"> <main role="main" class="devsite-main-content" > <div class="devsite-sidebar"> <div class="devsite-sidebar-content"> <devsite-toc class="devsite-nav" role="navigation" aria-label="On this page" depth="2" scrollbars disabled></devsite-toc> <devsite-recommendations-sidebar class="nocontent devsite-nav"> </devsite-recommendations-sidebar> </div> </div> <devsite-content> <article class="devsite-article"><style> /* Styles inlined from /assets/css/compose-tutorial.css */ /* VARIABLES */ :root { --brand-dark-blue: #003147; --banner-height: 350px; --hero-height: 276px; --headline-font-family: Google Sans, Noto Sans, Noto Sans JP, Noto Sans KR, Noto Naskh Arabic, Noto Sans Thai, Noto Sans Hebrew, Noto Sans Bengali, sans-serif; } /* AUX CLASSES */ .dac-tutorial-page .dac-indent { max-width: 610px; } .dac-tutorial-page .dac-tutorial-lessons { margin: 0 40px; } .dac-tutorial-page .dac-indent-full-width .dac-indent { max-width: 100%; } .dac-tutorial-page .dac-flex-spread { align-items: baseline; display: flex; flex: 1; justify-content: space-between; } /* END AUX CLASSES */ /* OVERRIDES */ body.dac-tutorial-page[layout=full] devsite-code { overflow: hidden; } .dac-tutorial-page .devsite-landing-row-item-image--with-padding figure { background: transparent; } .dac-tutorial-page .devsite-landing-row-item-image--with-padding img { padding: 27px 34px; } .dac-tutorial-page .dac-center { justify-content: center; } .dac-tutorial-page .dac-center .devsite-landing-row-item-buttons { justify-content: center; } .dac-tutorial-page .devsite-code-buttons-container { left: 0; } .dac-tutorial-page devsite-code .devsite-toggle-dark, .dac-tutorial-page devsite-code .devsite-toggle-light, .dac-tutorial-page devsite-code[no-copy] .devsite-code-buttons-container { display: none !important; } .dac-tutorial-page .dac-bullet-list .devsite-landing-row-item-list-item { list-style: disc; } /* END OVERRIDES */ /* MOBILE */ android-sticky-toc[embedded] { margin-left: 130px; } .dac-tutorial-page .dac-step-preview-mobile, .dac-tutorial-page .hero-container .hero-image-mobile { display: none; } /* END MOBILE */ /* TYPOGRAPHY */ .dac-tutorial-page .devsite-main-content .hero h1 { color: #fff; margin: 0; font: 600 48px/66px var(--headline-font-family); position: relative; } .dac-tutorial-page .dac-lesson-wrapper h4 { margin: 40px 0 20px; } /* END TYPOGRAPHY */ /* HERO BANNER */ .dac-tutorial-page .dac-hero-container { padding: 0; } .dac-tutorial-page .dac-hero-container .devsite-landing-row-html { margin: 0; max-width: initial; padding: 0; } .dac-tutorial-page .hero { padding: 96px 0 0; position: relative; } .dac-tutorial-page .banner { background-color: var(--brand-dark-blue); height: var(--banner-height); position: absolute; top: 0; width: 100%; } .dac-tutorial-page .hero-container { display: flex; flex-wrap: wrap; margin: 0 auto; max-width: 1520px; padding: 0 40px; } .dac-tutorial-page .dac-hero-container .hero-image .dac-media-video { left: 19px; position: absolute; top: 50px; width: 233px; } .dac-tutorial-page .hero-text { flex: 6; } .dac-tutorial-page .hero-header { min-height: var(--hero-height); } .dac-tutorial-page .subtitle { color: #fff; font-size: 14px; font-weight: 500; letter-spacing: 1.5px; margin-bottom: 8px; position: relative; text-transform: uppercase; } .dac-tutorial-page .hero-actions { color: #fff; display: flex; margin-top: 24px; padding: 0; position: relative; } .dac-tutorial-page .hero-actions li { display: flex; margin: 0; } .dac-tutorial-page .hero-actions .action-icon.timer { background: url('/images/jetpack/icons/compose-lessons-icon.svg') 50% no-repeat; background-size: 100%; height: 24px; width: 24px; } .dac-tutorial-page .hero-actions .action-icon.get-started { background: url('/images/jetpack/icons/android-studio.svg') 50% no-repeat; background-size: 100%; height: 24px; margin-left: 16px; width: 24px; } .dac-tutorial-page .hero-actions .action-text { margin-left: 8px; } .dac-tutorial-page .hero-actions .action-text a { color: #fff; } .dac-tutorial-page .hero-actions, .dac-tutorial-page .hero-actions-mobile { margin-top: 24px; padding: 0; position: relative; } .dac-tutorial-page .hero-actions { display: flex; color: #fff; } .dac-tutorial-page .hero-actions-mobile { display: none; } .dac-tutorial-page .hero-actions .action-icon.timer { background-image: url('/images/jetpack/icons/compose-lessons-icon.svg'); } .dac-tutorial-page .hero-actions-mobile .action-icon.timer { background-image: url('/images/jetpack/icons/compose-lessons-icon-mobile.svg'); } .dac-tutorial-page .hero-actions .action-icon.timer, .dac-tutorial-page .hero-actions-mobile .action-icon.timer, .dac-tutorial-page .hero-actions .action-icon.get-started, .dac-tutorial-page .hero-actions-mobile .action-icon.get-started { background-position: 50%; background-repeat: no-repeat; background-size: 100%; height: 24px; width: 24px; } .dac-tutorial-page .hero-actions .action-icon.get-started { background-image: url('/images/jetpack/icons/android-studio.svg'); margin-left: 16px; } .dac-tutorial-page .hero-actions-mobile .action-icon.get-started { background-image: url('/images/jetpack/icons/android-studio-mobile.svg'); } .dac-tutorial-page .description-container { margin-top: 16px; } .dac-tutorial-page .description-container p { font: 400 20px/32px var(--headline-font-family); } .dac-tutorial-page .hero-container .hero-image { margin-left: 50px; position: relative; z-index: 1; } .dac-tutorial-page .hero-text.dac-indent { margin-right: 100px; } .dac-tutorial-page .hero-image img { display: block; /* Overwriting app.css styles */ margin: 0 auto; max-width: 300px; padding-top: 0; } /* END HERO */ /* LAYOUT */ .dac-tutorial-page .dac-tutorial-content { margin-top: 120px; } .dac-tutorial-page .dac-bullet-list ul { margin-left: 20px; } .dac-tutorial-page .dac-tutorial-done { margin: 0 auto; max-width: 1100px; } .dac-tutorial-page .dac-cards-2-1-1 .devsite-landing-row-item { -webkit-box-orient: horizontal; -webkit-box-direction: normal; -webkit-flex-direction: row; -moz-box-orient: horizontal; -moz-box-direction: normal; -ms-flex-direction: row; flex-direction: row } .dac-tutorial-page .dac-cards-2-1-1 .devsite-landing-row-item:first-of-type { -webkit-box-flex: 0; -webkit-flex: 0 0 calc(50% - 19px); -moz-box-flex: 0; -ms-flex: 0 0 calc(50% - 19px); flex: 0 0 calc(50% - 19px); } .dac-tutorial-page .dac-cards-2-1-1 .devsite-landing-row-item-media { display: flex; justify-content: center; order: 2; padding: 32px 32px 32px 0; } .dac-tutorial-page .dac-cards-2-1-1 .devsite-landing-row-item-image { align-self: center; } .dac-tutorial-page .dac-illustration-jetnews { display: flex; flex-direction: row; } .dac-tutorial-page .dac-illustration-jetnews .devsite-landing-row-item-description { flex: 0 1; flex-basis: calc((200% - 40px)/3); margin: 0 24px 0 0; } .dac-tutorial-page .dac-illustration-jetnews::after { background: url(/images/jetpack/jetnews-app-card-img.png) center / 70% no-repeat; } /* END LAYOUT */ /* TOGGLE */ .dac-tutorial-page .dac-preview-toggle-wrapper { top: 42px; } .dac-tutorial-page .dac-preview-toggle-wrapper .dac-preview-toggle { cursor: pointer; font-size: 16px; font-weight: 500; line-height: 24px; letter-spacing: .5px; min-width: 125px; position: absolute; right: 70px; text-transform: uppercase; } .dac-tutorial-page .dac-preview-toggle-wrapper .dac-preview-phone { margin-right: 16px; margin-top: 180px; width: 260px; } .dac-tutorial-page .dac-preview-video { border-radius: 23px; } /* END TOGGLE */ /* LESSONS */ .dac-tutorial-page .dac-tutorial-lessons { flex: 10; width: 100%; } .dac-tutorial-page .dac-tutorial-lesson-intro { padding-bottom: 120px; } .dac-tutorial-page .dac-tutorial-lesson-intro h2 { margin-top: 0; } .dac-tutorial-page .dac-tutorial-lesson-intro .dac-nav-top { background: url(/images/jetpack/icons/arrow-upward.svg) 50% no-repeat; background-size: 100%; cursor: pointer; display: none; float: right; height: 24px; margin-left: 16px; width: 24px; } .dac-tutorial-page .dac-tutorial-lesson-intro p { font: 400 20px/32px var(--headline-font-family); } .dac-tutorial-page .dac-tutorial-lesson-intro-asset { height: 395px; width: 612px; } .dac-tutorial-page .dac-lesson-wrapper { display: flex; margin-bottom: 192px; } /* END LESSONS */ /* STEPS */ .dac-tutorial-page .dac-step-wrapper { flex: 4; margin-bottom: 50vh; min-width: 300px; } .dac-tutorial-page .dac-step-wrapper section { display: flex; margin-bottom: 150px; padding: 0; } .dac-tutorial-page .dac-step-wrapper section .devsite-landing-row-group { margin-left: 0; padding: 28px 56px 28px 0; } .dac-tutorial-page .dac-step-wrapper .dac-tutorial-download { width: 50%; } .dac-tutorial .dac-step-imports { font } /* END STEPS */ /* STEP PREVIEWS */ .dac-tutorial-page .dac-preview-wrapper { flex: 6; height: calc(100vh - 112px) !important; min-height: 512px; min-width: 580px; max-width: 605px; top: 64px !important; } /* END STEP PREVIEWS */ /* CODE SNIPPETS */ .dac-tutorial-page devsite-code { background: #283142; border-radius: 0 27px 27px 0; height: calc(100vh - 112px); overflow: hidden; position: relative; min-height: 512px; min-width: 580px; max-width: 605px; } .dac-tutorial-page devsite-code .devsite-icon-copy { cursor: pointer !important; position: absolute; right: 37px; top: 10px; } .dac-tutorial-page devsite-code pre { height: inherit; padding: 40px 0 0 28px; } .dac-tutorial-page .dac-preview-screenshot { display: flex; flex-direction: column; justify-content: center; min-height: calc(100vh - 112px); } /* Screenshot animations */ /* TODO: Move this to android-sticky-lesson CE (core) */ .dac-tutorial-page .dac-preview-wrapper .dac-step-preview.screenshot { transition: visibility 0s 300ms, opacity 300ms ease-out; will-change: visibility, opacity; } .dac-tutorial-page .dac-preview-wrapper .dac-step-preview.screenshot.active { transition: visibility 0s, opacity 300ms ease-in; } /* End screenshot animations */ /* END CODE SNIPPETS */ /* MEDIA QUERIES */ @media screen and (max-width: 1050px) { /* RESOURCE CARDS */ .dac-tutorial-page .dac-cards-2-1-1 .devsite-landing-row-group { -webkit-flex-direction: column; -ms-flex-direction: column; flex-direction: column; } .dac-tutorial-page .dac-cards-2-1-1 .devsite-landing-row-item:not(first-child) { margin: 32px 0 0 !important; } /* END RESOURCE CARDS */ } @media screen and (max-width: 1000px) { .dac-tutorial-page .dac-preview-wrapper { display: none; } /* PREVIEW TOGGLE */ .dac-tutorial-page .dac-step-wrapper [id^=tut] .dac-preview-toggle-wrapper.toggle, .dac-tutorial-page .dac-step-wrapper [id^=tut] .dac-preview-toggle { border-left: 4px solid #3ddc84; border-radius: 4px; padding-left: 12px; } .dac-tutorial-page .dac-step-wrapper [id^=tut] .dac-preview-toggle-wrapper.toggle .dac-preview-toggle { border: none; } /* END PREVIEW TOGGLE */ .dac-tutorial-page .dac-tutorial-lesson-intro .dac-nav-top, .dac-tutorial-page .dac-step-preview-mobile { display: block; } .dac-tutorial-page .dac-lesson-wrapper { margin-bottom: 0; } .dac-tutorial-page .dac-tutorial-lesson-intro { padding-bottom: 56px; } .dac-tutorial-page .dac-tutorial-lesson-intro-asset { height: auto; width: 100%; } .dac-tutorial-page .dac-step-wrapper, .dac-tutorial-page .dac-step-wrapper section { margin-bottom: 56px; } .dac-tutorial-page .dac-step-wrapper section .devsite-landing-row-group { flex-direction: column; padding: 0; width: 100%; } .dac-tutorial-page .dac-preview-screenshot { margin-top: 16px; min-height: 0; } .dac-tutorial-page .hero-text.dac-indent { margin-right: 0; } .dac-tutorial-page .dac-indent, .dac-tutorial-page .dac-tutorial-done { margin: 0; max-width: 100%; } .dac-tutorial-page .dac-tutorial-done { padding: 0; } .dac-tutorial-page devsite-code { height: auto; min-height: 100px; min-width: 100%; } /* TYPOGRAPHY */ .dac-tutorial-page .devsite-main-content h1 { font-size: 34px; line-height: 40px; } @media screen and (max-width: 770px) { /* HERO */ .dac-tutorial-page .hero { padding-top: 50px; } .dac-tutorial-page .dac-tutorial-lessons { margin: 0; } .dac-tutorial-page .hero-actions-mobile { display: flex; list-style: none; } .dac-tutorial-page .dac-tutorial-content { margin-top: 70px; } .dac-tutorial-page .hero-actions-mobile li { display: flex; margin-right: 15px; } .dac-tutorial-page .hero-actions-mobile .action-icon.timer, .dac-tutorial-page .hero-actions-mobile .action-icon.get-started { margin-right: 5px; } .dac-tutorial-page .hero-actions-mobile li:last-of-type a { color: black; } .dac-tutorial-page .banner { background: none; } .dac-tutorial-page .hero-container .hero-image, .dac-tutorial-page .hero-actions { display: none; } .dac-tutorial-page .hero-container { flex-direction: column; } .dac-tutorial-page .hero-container .hero-header { min-height: 0; } .dac-tutorial-page .hero-container .hero-header .subtitle, .dac-tutorial-page .hero-container .hero-header h1 { color: inherit; } .dac-tutorial-page .hero-container .hero-image-mobile { background: var(--brand-dark-blue); display: block; min-height: 250px; overflow: hidden; position: relative; } .dac-tutorial-page .hero-container .hero-image-mobile img { display: block; left: 0; margin: 5px auto 0 auto; max-width: 191px; position: absolute; right: 0; } .dac-tutorial-page .hero-container .hero-image { align-items: flex-start; } /* END HERO */ } @media screen and (max-width: 600px) { .dac-tutorial-page .hero-container .hero-image { margin-top: 40px; } .dac-tutorial-page .dac-cards-2-1-1 .devsite-landing-row-item-media { display: none; } .dac-tutorial-page .dac-illustration-jetnews { display: block; } .dac-tutorial-page .dac-illustration-jetnews::after { background: none; min-height: 0; } .dac-tutorial-page .dac-illustration-jetnews .devsite-landing-row-item-description-content::after { background: url('/images/jetpack/jetnews-app-card-img.png') center / 70% no-repeat; content: ""; display: block; margin: auto; min-height: 250px; } } /* END MEDIA QUERIES */ </style> <div class="devsite-article-meta nocontent" role="navigation"> <ul class="devsite-breadcrumb-list" aria-label="Breadcrumb"> <li class="devsite-breadcrumb-item "> <a href="https://developer.android.com/" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Breadcrumbs" data-value="1" track-type="globalNav" track-name="breadcrumb" track-metadata-position="1" track-metadata-eventdetail="Android Developers" > Android Developers </a> </li> <li class="devsite-breadcrumb-item "> <div class="devsite-breadcrumb-guillemet material-icons" aria-hidden="true"></div> <a href="https://developer.android.com/develop" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Breadcrumbs" data-value="2" track-type="globalNav" track-name="breadcrumb" track-metadata-position="2" track-metadata-eventdetail="Develop" > Develop </a> </li> <li class="devsite-breadcrumb-item "> <div class="devsite-breadcrumb-guillemet material-icons" aria-hidden="true"></div> <a href="https://developer.android.com/develop/core-areas" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Breadcrumbs" data-value="3" track-type="globalNav" track-name="breadcrumb" track-metadata-position="3" track-metadata-eventdetail="Core areas" > Core areas </a> </li> <li class="devsite-breadcrumb-item "> <div class="devsite-breadcrumb-guillemet material-icons" aria-hidden="true"></div> <a href="https://developer.android.com/develop/ui" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Breadcrumbs" data-value="4" track-type="globalNav" track-name="breadcrumb" track-metadata-position="4" track-metadata-eventdetail="Jetpack Compose" > UI </a> </li> <li class="devsite-breadcrumb-item "> <div class="devsite-breadcrumb-guillemet material-icons" aria-hidden="true"></div> <a href="https://developer.android.com/develop/ui/compose/tutorial" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Breadcrumbs" data-value="5" track-type="globalNav" track-name="breadcrumb" track-metadata-position="5" track-metadata-eventdetail="" > Tutorial </a> </li> </ul> </div> <devsite-feature-tooltip ack-key="AckCollectionsBookmarkTooltipDismiss" analytics-category="Site-Wide Custom Events" analytics-action-show="Callout Profile displayed" analytics-action-close="Callout Profile dismissed" analytics-label="Create Collection Callout" class="devsite-page-bookmark-tooltip nocontent" dismiss-button="true" id="devsite-collections-dropdown" dismiss-button-text="Dismiss" close-button-text="Got it"> <devsite-bookmark></devsite-bookmark> <span slot="popout-heading"> Stay organized with collections </span> <span slot="popout-contents"> Save and categorize content based on your preferences. </span> </devsite-feature-tooltip> <devsite-toc class="devsite-nav" depth="2" devsite-toc-embedded disabled> </devsite-toc> <div class="devsite-article-body clearfix "> <section class="devsite-landing-row devsite-landing-row-1-up dac-hero-container dac-banner-wide" header-position="top" > <div class="devsite-landing-row-inner"> <div class="devsite-landing-row-html"> <div class="hero"> <div class="banner"></div> <div class="hero-container"> <div class="hero-text dac-indent"> <div class="hero-header"> <div class="subtitle">Tutorial</div> <h1 id="jetpack-compose-tutorial" data-text="Jetpack Compose Tutorial" tabindex="-1">Jetpack Compose Tutorial</h1> <ul class="hero-actions"> <li> <div class="action-icon timer"></div> <div class="action-text">4 lessons</div> </li> <li> <div class="action-icon get-started"></div> <div class="action-text"> <a href="/develop/ui/compose/setup">Get set up ></a> </div> </li> </ul> </div> <div class="description-container"> <p class="hero-description"> Jetpack Compose is a modern toolkit for building native Android UI. Jetpack Compose simplifies and accelerates UI development on Android with less code, powerful tools, and intuitive Kotlin APIs. </p> <p class="hero-description"> In this tutorial, you'll build a simple UI component with declarative functions. You won't be editing any XML layouts or using the Layout Editor. Instead, you will call composable functions to define what elements you want, and the Compose compiler will do the rest. </p> <div class="hero-image-mobile"> <img class="dac-preview-phone full-preview" src="/static/develop/ui/compose/images/compose-tutorial/00-hero-device.png" alt="Full Preview"> </div> <ul class="hero-actions-mobile"> <li> <div class="action-icon timer"></div> <div class="action-text">4 lessons</div> </li> <li> <div class="action-icon get-started"></div> <div class="action-text"> <a href="/develop/ui/compose/setup">Get setup ></a> </div> </li> </ul> </div> </div> <div class="hero-image"> <img class="dac-preview-phone full-preview" src="/static/develop/ui/compose/images/compose-tutorial/hero.png" alt="Full Preview"> </div> </div> </div> </div> </div> </section> <section class="devsite-landing-row devsite-landing-row-1-up android-row-padding-top-xlarge-bottom-small" header-position="top" > <div class="devsite-landing-row-inner"> <div class="devsite-landing-row-html"> <android-sticky-toc embedded class="android-sticky-toc" eyebrow-text="Tutorial" back-to-top-text="Learning the basics of Compose"> </android-sticky-toc> <section class="dac-tutorial-content dac-flex-spread"> <div class="dac-tutorial-lessons"> <div class="dac-tutorial-lesson-intro dac-indent"> <a href="#top_of_page"><div class="dac-nav-top"></div></a> <h2 sticky-toc sticky-toc-text="1: Composable functions" id="lesson-1:-composable-functions" data-text="Lesson 1: Composable functions" tabindex="-1">Lesson 1: Composable functions</h2> <p> Jetpack Compose is built around composable functions. These functions let you define your app's UI programmatically by describing how it should look and providing data dependencies, rather than focusing on the process of the UI's construction (initializing an element, attaching it to a parent, etc.). To create a composable function, just add the <code translate="no" dir="ltr">@Composable</code> annotation to the function name. </p> <div class="dac-tutorial-lesson-intro-asset"> <img alt src="/static/develop/ui/compose/images/compose-tutorial/lesson1-01.svg"> </div> </div> <android-sticky-lesson lesson-id="1" step-ids="tut-step-1,tut-step-2,tut-step-3,tut-step-4"> <!-- Please do not remove wrapping div's --> <div class="dac-lesson-wrapper"> <div class="dac-step-wrapper"> <!-- steps --> <section id="tut-step-1" class="devsite-landing-row"> <div class="devsite-landing-row-group"> <div class="devsite-landing-row-item-body"> <h4 sticky-toc id="add-a-text-element" data-text="Add a text element" tabindex="-1">Add a text element</h4> <div class="devsite-landing-row-item-description-content"> <p> To begin, download the most recent version of <a href="https://developer.android.com/studio" > Android Studio</a>, and create an app by selecting <strong>New Project</strong>, and under the <strong>Phone and Tablet</strong> category, select <strong>Empty Activity</strong>. Name your app <strong>ComposeTutorial</strong> and click <strong>Finish</strong>. The default template already contains some Compose elements, but in this tutorial you will build it up step by step. </p> <p> First, display a “Hello world!” text by adding a text element inside the <code translate="no" dir="ltr">onCreate</code> method. You do this by defining a content block, and calling the <a href="/reference/kotlin/androidx/compose/material3/package-summary#Text(kotlin.String,androidx.compose.ui.Modifier,androidx.compose.ui.graphics.Color,androidx.compose.ui.unit.TextUnit,androidx.compose.ui.text.font.FontStyle,androidx.compose.ui.text.font.FontWeight,androidx.compose.ui.text.font.FontFamily,androidx.compose.ui.unit.TextUnit,androidx.compose.ui.text.style.TextDecoration,androidx.compose.ui.text.style.TextAlign,androidx.compose.ui.unit.TextUnit,androidx.compose.ui.text.style.TextOverflow,kotlin.Boolean,kotlin.Int,kotlin.Function1,androidx.compose.ui.text.TextStyle)"> <code translate="no" dir="ltr">Text</code></a> composable function. The <code translate="no" dir="ltr">setContent</code> block defines the activity's layout where composable functions are called. Composable functions can only be called from other composable functions. </p> <p> Jetpack Compose uses a Kotlin compiler plugin to transform these composable functions into the app's UI elements. For example, the <code translate="no" dir="ltr">Text</code> composable function that is defined by the Compose UI library displays a text label on the screen. </p> </div> </div> <div class="dac-step-preview-mobile"> <devsite-code dark-code class="dac-tutorial-code"> <pre is-upgraded class="prettyprint lang-kotlin dac-compose-snippet" translate="no" dir="ltr"> import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent <strong>import androidx.compose.material3.Text</strong> class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) <strong>setContent { Text("Hello world!") }</strong> } } </pre> </devsite-code> <div class="dac-preview-toggle-wrapper"> <div class="dac-preview-toggle show">show preview</div> <div class="dac-preview-toggle hide">hide preview</div> <img alt class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson1-02.png"> </div> </div> </div> </section> <section id="tut-step-2" class="devsite-landing-row"> <div class="devsite-landing-row-group"> <div class="devsite-landing-row-item-body"> <h4 sticky-toc id="define-a-composable-function" data-text="Define a composable function" tabindex="-1">Define a composable function</h4> <div class="devsite-landing-row-item-description-content"> <p> To make a function composable, add the <code translate="no" dir="ltr">@Composable</code> annotation. To try this out, define a <code translate="no" dir="ltr">MessageCard</code> function which is passed a name, and uses it to configure the text element. </p> </div> </div> <div class="dac-step-preview-mobile"> <devsite-code dark-code class="dac-tutorial-code"> <pre is-upgraded class="prettyprint lang-kotlin dac-compose-snippet" translate="no" dir="ltr"> // ... <strong>import androidx.compose.runtime.Composable</strong> class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { <strong>MessageCard("Android")</strong> } } } <strong>@Composable fun MessageCard(name: String) { Text(text = "Hello $name!") } </strong> </pre> </devsite-code> <div class="dac-preview-toggle-wrapper"> <div class="dac-preview-toggle show">show preview</div> <div class="dac-preview-toggle hide">hide preview</div> <img alt class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson1-03.png"> </div> </div> </div> </section> <section id="tut-step-3" class="devsite-landing-row"> <div class="devsite-landing-row-group"> <div class="devsite-landing-row-item-body"> <h4 sticky-toc id="preview-your-function-in-android-studio" data-text="Preview your function in Android Studio" tabindex="-1">Preview your function in Android Studio</h4> <div class="devsite-landing-row-item-description-content"> <p> The <code translate="no" dir="ltr">@Preview</code> annotation lets you preview your composable functions within Android Studio without having to build and install the app to an Android device or emulator. The annotation must be used on a composable function that does not take in parameters. For this reason, you can't preview the <code translate="no" dir="ltr">MessageCard</code> function directly. Instead, make a second function named <code translate="no" dir="ltr">PreviewMessageCard</code>, which calls <code translate="no" dir="ltr">MessageCard</code> with an appropriate parameter. Add the <code translate="no" dir="ltr">@Preview</code> annotation before <code translate="no" dir="ltr">@Composable</code>. </p> </div> </div> <div class="dac-step-preview-mobile"> <devsite-code dark-code class="dac-tutorial-code"> <pre is-upgraded class="prettyprint lang-kotlin dac-compose-snippet" translate="no" dir="ltr"> // ... <strong>import androidx.compose.ui.tooling.preview.Preview</strong> @Composable fun MessageCard(name: String) { Text(text = "Hello $name!") } <strong>@Preview @Composable fun PreviewMessageCard() { MessageCard("Android") }</strong> </pre> </devsite-code> <div class="dac-preview-toggle-wrapper"> <div class="dac-preview-toggle show">show preview</div> <div class="dac-preview-toggle hide">hide preview</div> <img alt class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson1-03.png"> </div> </div> </div> </section> <section id="tut-step-4" class="devsite-landing-row"> <div class="devsite-landing-row-group"> <div class="devsite-landing-row-item-body"> <div class="devsite-landing-row-item-description-content"> <p> Rebuild your project. The app itself doesn't change, since the new <code translate="no" dir="ltr">PreviewMessageCard</code> function isn't called anywhere, but Android Studio adds a preview window which you can expand by clicking on the split (design/code) view. This window shows a preview of the UI elements created by composable functions marked with the <code translate="no" dir="ltr">@Preview</code> annotation. To update the previews at any time, click the refresh button at the top of the preview window. </p> </div> </div> <div class="dac-step-preview-mobile"> <div class="dac-preview-screenshot"> <img alt="Preview of a composable function in Android Studio" class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson1-04.png"> </div> </div> </div> </section> </div> <!-- preview assets --> <div class="dac-preview-wrapper"> <div id="tut-step-1-preview" class="dac-step-preview active"> <devsite-code dark-code class="dac-tutorial-code"> <pre is-upgraded class="prettyprint lang-kotlin dac-compose-snippet" translate="no" dir="ltr"> import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent <strong>import androidx.compose.material3.Text</strong> class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) <strong>setContent { Text("Hello world!") }</strong> } } </pre> </devsite-code> <div class="dac-preview-toggle-wrapper"> <div class="dac-preview-toggle show">show preview</div> <div class="dac-preview-toggle hide">hide preview</div> <img alt class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson1-02.png"> </div> </div> <div id="tut-step-2-preview" class="dac-step-preview"> <devsite-code dark-code class="dac-tutorial-code"> <pre is-upgraded class="prettyprint lang-kotlin dac-compose-snippet" translate="no" dir="ltr"> // ... <strong>import androidx.compose.runtime.Composable</strong> class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { <strong>MessageCard("Android")</strong> } } } <strong>@Composable fun MessageCard(name: String) { Text(text = "Hello $name!") } </strong> </pre> </devsite-code> <div class="dac-preview-toggle-wrapper"> <div class="dac-preview-toggle show">show preview</div> <div class="dac-preview-toggle hide">hide preview</div> <img alt class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson1-03.png"> </div> </div> <div id="tut-step-3-preview" class="dac-step-preview"> <devsite-code dark-code class="dac-tutorial-code"> <pre is-upgraded class="prettyprint lang-kotlin dac-compose-snippet" translate="no" dir="ltr"> // ... <strong>import androidx.compose.ui.tooling.preview.Preview</strong> @Composable fun MessageCard(name: String) { Text(text = "Hello $name!") } <strong>@Preview @Composable fun PreviewMessageCard() { MessageCard("Android") }</strong> </pre> </devsite-code> <div class="dac-preview-toggle-wrapper"> <div class="dac-preview-toggle show">show preview</div> <div class="dac-preview-toggle hide">hide preview</div> <img alt class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson1-03.png"> </div> </div> <div id="tut-step-4-preview" class="dac-step-preview screenshot"> <div class="dac-preview-screenshot"> <img alt="Preview of a composable function in Android Studio" class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson1-04.png"> </div> </div> </div> </div> </android-sticky-lesson> <div class="dac-tutorial-lesson-intro dac-indent"> <a href="#top_of_page"><div class="dac-nav-top"></div></a> <h2 sticky-toc sticky-toc-text="2: Layouts" id="lesson-2:-layouts" data-text="Lesson 2: Layouts" tabindex="-1">Lesson 2: Layouts</h2> <p> UI elements are hierarchical, with elements contained in other elements. In Compose, you build a UI hierarchy by calling composable functions from other composable functions. </p> <div class="dac-tutorial-lesson-intro-asset"> <img alt src="/static/develop/ui/compose/images/compose-tutorial/lesson2-01.svg"> </div> </div> <android-sticky-lesson lesson-id="2" step-ids="tut-step-1,tut-step-2,tut-step-3,tut-step-4,tut-step-5"> <!-- Please do not remove wrapping div's --> <div class="dac-lesson-wrapper"> <div class="dac-step-wrapper"> <!-- steps --> <section id="tut-step-1" class="devsite-landing-row"> <div class="devsite-landing-row-group"> <div class="devsite-landing-row-item-body"> <h4 sticky-toc id="add-multiple-texts" data-text="Add multiple texts" tabindex="-1">Add multiple texts</h4> <div class="devsite-landing-row-item-description-content"> <p> So far you’ve built your first composable function and preview! To discover more Jetpack Compose capabilities, you’re going to build a simple messaging screen containing a list of messages that can be expanded with some animations. </p> <p> Start by making the message composable richer by displaying the name of its author and a message content. You need to first change the composable parameter to accept a <code translate="no" dir="ltr">Message</code> object instead of a <code translate="no" dir="ltr">String</code>, and add another <code translate="no" dir="ltr">Text</code> composable inside the <code translate="no" dir="ltr">MessageCard</code> composable. Make sure to update the preview as well. </p> </div> </div> <div class="dac-step-preview-mobile"> <devsite-code dark-code class="dac-tutorial-code"> <pre is-upgraded class="prettyprint lang-kotlin dac-compose-snippet" translate="no" dir="ltr"> // ... class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { <strong>MessageCard(Message("Android", "Jetpack Compose"))</strong> } } } <strong>data class Message(val author: String, val body: String) @Composable fun MessageCard(msg: Message) { Text(text = msg.author) Text(text = msg.body) }</strong> @Preview @Composable fun PreviewMessageCard() { <strong>MessageCard( msg = Message("Lexi", "Hey, take a look at Jetpack Compose, it's great!") )</strong> } </pre> </devsite-code> <div class="dac-preview-toggle-wrapper"> <div class="dac-preview-toggle show">show preview</div> <div class="dac-preview-toggle hide">hide preview</div> <img alt class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson2-02.png"> </div> </div> </div> </section> <section id="tut-step-2" class="devsite-landing-row"> <div class="devsite-landing-row-group"> <div class="devsite-landing-row-item-body"> <div class="devsite-landing-row-item-description-content"> <p> This code creates two text elements inside the content view. However, since you haven't provided any information about how to arrange them, the text elements are drawn on top of each other, making the text unreadable. </p> </div> </div> <!-- <div class="dac-step-preview-mobile"> <div class="dac-preview-screenshot"> <img alt="Preview of two overlapping Text composables" class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson2-03.png"> </div> </div> --> </div> </section> <section id="tut-step-3" class="devsite-landing-row"> <div class="devsite-landing-row-group"> <div class="devsite-landing-row-item-body"> <h4 sticky-toc id="using-a-column" data-text="Using a Column" tabindex="-1">Using a Column</h4> <div class="devsite-landing-row-item-description-content"> <p> The <a href="/reference/kotlin/androidx/compose/foundation/layout/package-summary#Column(androidx.compose.ui.Modifier,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.ui.Alignment.Horizontal,kotlin.Function1)(androidx.compose.ui.Modifier,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.ui.Alignment.Horizontal,kotlin.Function1)"> <code translate="no" dir="ltr">Column</code></a> function lets you arrange elements vertically. Add <code translate="no" dir="ltr">Column</code> to the <code translate="no" dir="ltr">MessageCard</code> function. <br> You can use <a href="/reference/kotlin/androidx/compose/foundation/layout/package-summary#Row(androidx.compose.ui.Modifier,androidx.compose.foundation.layout.Arrangement.Horizontal,androidx.compose.ui.Alignment.Vertical,kotlin.Function1)(androidx.compose.ui.Modifier,androidx.compose.foundation.layout.Arrangement.Horizontal,androidx.compose.ui.Alignment.Vertical,kotlin.Function1)"> <code translate="no" dir="ltr">Row</code></a> to arrange items horizontally and <a href="/reference/kotlin/androidx/compose/foundation/layout/package-summary#Box(androidx.compose.ui.Modifier)"> <code translate="no" dir="ltr">Box</code></a> to stack elements. </p> </div> </div> <div class="dac-step-preview-mobile"> <devsite-code dark-code class="dac-tutorial-code"> <pre is-upgraded class="prettyprint lang-kotlin dac-compose-snippet" translate="no" dir="ltr"> // ... <strong>import androidx.compose.foundation.layout.Column @Composable fun MessageCard(msg: Message) { Column { Text(text = msg.author) Text(text = msg.body) } } </strong> </pre> </devsite-code> <div class="dac-preview-toggle-wrapper"> <div class="dac-preview-toggle show">show preview</div> <div class="dac-preview-toggle hide">hide preview</div> <img alt class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson2-04.png"> </div> </div> </div> </section> <section id="tut-step-4" class="devsite-landing-row"> <div class="devsite-landing-row-group"> <div class="devsite-landing-row-item-body"> <h4 sticky-toc id="add-an-image-element" data-text="Add an image element" tabindex="-1">Add an image element</h4> <div class="devsite-landing-row-item-description-content"> <p> Enrich your message card by adding a profile picture of the sender. Use the <a href="/studio/write/resource-manager#import">Resource Manager</a> to import an image from your photo library or use <a href="/static/develop/ui/compose/images/compose-tutorial/profile_picture.png">this one</a>. Add a <code translate="no" dir="ltr">Row</code> composable to have a well structured design and an <a href="/reference/kotlin/androidx/compose/foundation/package-summary#Image(androidx.compose.ui.graphics.painter.Painter,kotlin.String,androidx.compose.ui.Modifier,androidx.compose.ui.Alignment,androidx.compose.ui.layout.ContentScale,kotlin.Float,androidx.compose.ui.graphics.ColorFilter)"> <code translate="no" dir="ltr">Image</code></a> composable inside it. </p> </div> </div> <div class="dac-step-preview-mobile"> <devsite-code dark-code class="dac-tutorial-code"> <pre is-upgraded class="prettyprint lang-kotlin dac-compose-snippet" translate="no" dir="ltr"> // ... <strong>import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Row import androidx.compose.ui.res.painterResource</strong> @Composable fun MessageCard(msg: Message) { <strong>Row { Image( painter = painterResource(R.drawable.profile_picture), contentDescription = "Contact profile picture", ) </strong> Column { Text(text = msg.author) Text(text = msg.body) } <strong> } </strong> } </pre> </devsite-code> <div class="dac-preview-toggle-wrapper"> <div class="dac-preview-toggle show">show preview</div> <div class="dac-preview-toggle hide">hide preview</div> <img alt="" class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson2-05.png"> </div> </div> </div> </section> <section id="tut-step-5" class="devsite-landing-row"> <div class="devsite-landing-row-group"> <div class="devsite-landing-row-item-body"> <h4 sticky-toc id="configure-your-layout" data-text="Configure your layout" tabindex="-1">Configure your layout</h4> <div class="devsite-landing-row-item-description-content"> <p> Your message layout has the right structure but its elements aren't well spaced and the image is too big! To decorate or configure a composable, Compose uses <strong>modifiers</strong>. They allow you to change the composable's size, layout, appearance or add high-level interactions, such as making an element clickable. You can chain them to create richer composables. You'll use some of them to improve the layout. </p> </div> <div class="dac-step-preview-mobile"> <devsite-code dark-code class="dac-tutorial-code"> <pre is-upgraded class="prettyprint lang-kotlin dac-compose-snippet" translate="no" dir="ltr"> // ... <strong>import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.CircleShape import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.unit.dp</strong> @Composable fun MessageCard(msg: Message) { <strong>// Add padding around our message Row(modifier = Modifier.padding(all = 8.dp)) {</strong> Image( painter = painterResource(R.drawable.profile_picture), contentDescription = "Contact profile picture", <strong>modifier = Modifier // Set image size to 40 dp .size(40.dp) // Clip image to be shaped as a circle .clip(CircleShape)</strong> ) <strong>// Add a horizontal space between the image and the column Spacer(modifier = Modifier.width(8.dp))</strong> Column { Text(text = msg.author) <strong>// Add a vertical space between the author and message texts Spacer(modifier = Modifier.height(4.dp))</strong> Text(text = msg.body) } <strong>}</strong> } </pre> </devsite-code> <div class="dac-preview-toggle-wrapper"> <div class="dac-preview-toggle show">show preview</div> <div class="dac-preview-toggle hide">hide preview</div> <img alt class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson2-06.png"> </div> </div> </div> </section> </div> <!-- preview assets --> <div class="dac-preview-wrapper"> <div id="tut-step-1-preview" class="dac-step-preview active"> <devsite-code dark-code class="dac-tutorial-code"> <pre is-upgraded class="prettyprint lang-kotlin dac-compose-snippet" translate="no" dir="ltr"> // ... class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { <strong>MessageCard(Message("Android", "Jetpack Compose"))</strong> } } } <strong>data class Message(val author: String, val body: String) @Composable fun MessageCard(msg: Message) { Text(text = msg.author) Text(text = msg.body) }</strong> @Preview @Composable fun PreviewMessageCard() { <strong>MessageCard( msg = Message("Lexi", "Hey, take a look at Jetpack Compose, it's great!") )</strong> } </pre> </devsite-code> <div class="dac-preview-toggle-wrapper"> <div class="dac-preview-toggle show">show preview</div> <div class="dac-preview-toggle hide">hide preview</div> <img alt class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson2-02.png"> </div> </div> <div id="tut-step-2-preview" class="dac-step-preview"> <div class="dac-preview-screenshot"> <img alt="Preview of two overlapping Text composables" class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson2-03.png"> </div> </div> <div id="tut-step-3-preview" class="dac-step-preview"> <devsite-code dark-code class="dac-tutorial-code"> <pre is-upgraded class="prettyprint lang-kotlin dac-compose-snippet" translate="no" dir="ltr"> // ... <strong>import androidx.compose.foundation.layout.Column @Composable fun MessageCard(msg: Message) { Column { Text(text = msg.author) Text(text = msg.body) } } </strong> </pre> </devsite-code> <div class="dac-preview-toggle-wrapper"> <div class="dac-preview-toggle show">show preview</div> <div class="dac-preview-toggle hide">hide preview</div> <img alt class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson2-04.png"> </div> </div> <div id="tut-step-4-preview" class="dac-step-preview"> <devsite-code dark-code class="dac-tutorial-code"> <pre is-upgraded class="prettyprint lang-kotlin dac-compose-snippet" translate="no" dir="ltr"> // ... <strong>import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Row import androidx.compose.ui.res.painterResource</strong> @Composable fun MessageCard(msg: Message) { <strong>Row { Image( painter = painterResource(R.drawable.profile_picture), contentDescription = "Contact profile picture", ) </strong> Column { Text(text = msg.author) Text(text = msg.body) } <strong> } </strong> } </pre> </devsite-code> <div class="dac-preview-toggle-wrapper"> <div class="dac-preview-toggle show">show preview</div> <div class="dac-preview-toggle hide">hide preview</div> <img alt="" class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson2-05.png"> </div> </div> <div id="tut-step-5-preview" class="dac-step-preview"> <devsite-code dark-code class="dac-tutorial-code"> <pre is-upgraded class="prettyprint lang-kotlin dac-compose-snippet" translate="no" dir="ltr"> // ... <strong>import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.CircleShape import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.unit.dp</strong> @Composable fun MessageCard(msg: Message) { <strong>// Add padding around our message Row(modifier = Modifier.padding(all = 8.dp)) {</strong> Image( painter = painterResource(R.drawable.profile_picture), contentDescription = "Contact profile picture", <strong>modifier = Modifier // Set image size to 40 dp .size(40.dp) // Clip image to be shaped as a circle .clip(CircleShape)</strong> ) <strong>// Add a horizontal space between the image and the column Spacer(modifier = Modifier.width(8.dp))</strong> Column { Text(text = msg.author) <strong>// Add a vertical space between the author and message texts Spacer(modifier = Modifier.height(4.dp))</strong> Text(text = msg.body) } <strong>}</strong> } </pre> </devsite-code> <div class="dac-preview-toggle-wrapper"> <div class="dac-preview-toggle show">show preview</div> <div class="dac-preview-toggle hide">hide preview</div> <img alt class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson2-06.png"> </div> </div> </div> </div> </android-sticky-lesson> <div class="dac-tutorial-lesson-intro dac-indent"> <a href="#top_of_page"><div class="dac-nav-top"></div></a> <h2 sticky-toc sticky-toc-text="3: Material Design" id="lesson-3:-material-design" data-text="Lesson 3: Material Design" tabindex="-1">Lesson 3: Material Design</h2> <p> Compose is built to support Material Design principles. Many of its UI elements implement Material Design out of the box. In this lesson, you'll style your app with Material Design widgets. </p> <div class="dac-tutorial-lesson-intro-asset"> <img alt src="/static/develop/ui/compose/images/compose-tutorial/lesson3-01.svg"> </div> </div> <android-sticky-lesson lesson-id="3" step-ids="tut-step-1,tut-step-2,tut-step-3,tut-step-4,tut-step-5,tut-step-6"> <!-- Please do not remove wrapping div's --> <div class="dac-lesson-wrapper"> <div class="dac-step-wrapper"> <!-- steps --> <section id="tut-step-1" class="devsite-landing-row"> <div class="devsite-landing-row-group"> <div class="devsite-landing-row-item-body"> <h4 sticky-toc id="use-material-design" data-text="Use Material Design" tabindex="-1">Use Material Design</h4> <div class="devsite-landing-row-item-description-content"> <p> Your message design now has a layout, but it doesn't look great yet. </p> <p> Jetpack Compose provides an implementation of Material Design 3 and its UI elements out of the box. You'll improve the appearance of our <code translate="no" dir="ltr">MessageCard</code> composable using Material Design styling. </p> <p> To start, wrap the <code translate="no" dir="ltr">MessageCard</code> function with the Material theme created in your project, <code translate="no" dir="ltr">ComposeTutorialTheme</code>, as well as a <code translate="no" dir="ltr">Surface</code>. Do it both in the <code translate="no" dir="ltr">@Preview</code> and in the <code translate="no" dir="ltr">setContent</code> function. Doing so will allow your composables to inherit styles as defined in your app's theme ensuring consistency across your app. </p> <p> Material Design is built around three pillars: <code translate="no" dir="ltr">Color</code>, <code translate="no" dir="ltr">Typography</code>, and <code translate="no" dir="ltr">Shape</code>. You will add them one by one. </p> <p class="note"> <b>Note:</b> the Empty Compose Activity template generates a default theme for your project that allows you to customize <a href="/reference/kotlin/androidx/compose/material3/package-summary#MaterialTheme(androidx.compose.material3.ColorScheme,androidx.compose.material3.Shapes,androidx.compose.material3.Typography,kotlin.Function0)"> <code translate="no" dir="ltr">MaterialTheme</code></a>. If you named your project anything different from <strong>ComposeTutorial</strong>, you can find your custom theme in the <code translate="no" dir="ltr">Theme.kt</code> file in the <code translate="no" dir="ltr">ui.theme</code> subpackage. </p> </div> </div> <div class="dac-step-preview-mobile"> <devsite-code dark-code class="dac-tutorial-code"> <pre is-upgraded class="prettyprint lang-kotlin dac-compose-snippet" translate="no" dir="ltr"> // ... class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) <strong>setContent { ComposeTutorialTheme { Surface(modifier = Modifier.fillMaxSize()) { MessageCard(Message("Android", "Jetpack Compose")) } } }</strong> } } <strong>@Preview @Composable fun PreviewMessageCard() { ComposeTutorialTheme { Surface { MessageCard( msg = Message("Lexi", "Take a look at Jetpack Compose, it's great!") ) } } }</strong> </pre> </devsite-code> <div class="dac-preview-toggle-wrapper"> <div class="dac-preview-toggle show">show preview</div> <div class="dac-preview-toggle hide">hide preview</div> <img alt class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson3-02.png"> </div> </div> </div> </section> <section id="tut-step-2" class="devsite-landing-row"> <div class="devsite-landing-row-group"> <div class="devsite-landing-row-item-body"> <h4 sticky-toc id="color" data-text="Color" tabindex="-1">Color</h4> <div class="devsite-landing-row-item-description-content"> <p> Use <code translate="no" dir="ltr">MaterialTheme.colorScheme</code> to style with colors from the wrapped theme. You can use these values from the theme anywhere a color is needed. This example uses dynamic theming colors (defined by device preferences). You can set <code translate="no" dir="ltr">dynamicColor</code> to <code translate="no" dir="ltr">false</code> in the <code translate="no" dir="ltr">MaterialTheme.kt</code> file to change this. </p> <p> Style the title and add a border to the image. </p> </div> </div> <div class="dac-step-preview-mobile"> <devsite-code dark-code class="dac-tutorial-code"> <pre is-upgraded class="prettyprint lang-kotlin dac-compose-snippet" translate="no" dir="ltr"> // ... <strong>import androidx.compose.foundation.border import androidx.compose.material3.MaterialTheme</strong> @Composable fun MessageCard(msg: Message) { Row(modifier = Modifier.padding(all = 8.dp)) { Image( painter = painterResource(R.drawable.profile_picture), contentDescription = null, modifier = Modifier .size(40.dp) .clip(CircleShape) <strong>.border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape)</strong> ) Spacer(modifier = Modifier.width(8.dp)) Column { <strong>Text( text = msg.author, color = MaterialTheme.colorScheme.secondary )</strong> Spacer(modifier = Modifier.height(4.dp)) Text(text = msg.body) } } } </pre> </devsite-code> <div class="dac-preview-toggle-wrapper"> <div class="dac-preview-toggle show">show preview</div> <div class="dac-preview-toggle hide">hide preview</div> <img alt class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson3-03.png"> </div> </div> </div> </section> <section id="tut-step-3" class="devsite-landing-row"> <div class="devsite-landing-row-group"> <div class="devsite-landing-row-item-body"> <h4 sticky-toc id="typography" data-text="Typography" tabindex="-1">Typography</h4> <div class="devsite-landing-row-item-description-content"> <p> Material Typography styles are available in the <code translate="no" ltr="dir" dir="ltr">MaterialTheme</code>, just add them to the <code translate="no" dir="ltr">Text</code> composables. </p> </div> </div> <div class="dac-step-preview-mobile"> <devsite-code dark-code class="dac-tutorial-code"> <pre is-upgraded class="prettyprint lang-kotlin dac-compose-snippet" translate="no" dir="ltr"> // ... @Composable fun MessageCard(msg: Message) { Row(modifier = Modifier.padding(all = 8.dp)) { Image( painter = painterResource(R.drawable.profile_picture), contentDescription = null, modifier = Modifier .size(40.dp) .clip(CircleShape) .border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape) ) Spacer(modifier = Modifier.width(8.dp)) Column { Text( text = msg.author, color = MaterialTheme.colorScheme.secondary, <strong>style = MaterialTheme.typography.titleSmall</strong> ) Spacer(modifier = Modifier.height(4.dp)) Text( text = msg.body, <strong>style = MaterialTheme.typography.bodyMedium</strong> ) } } } </pre> </devsite-code> <div class="dac-preview-toggle-wrapper"> <div class="dac-preview-toggle show">show preview</div> <div class="dac-preview-toggle hide">hide preview</div> <img alt class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson3-04.png"> </div> </div> </div> </section> <section id="tut-step-4" class="devsite-landing-row"> <div class="devsite-landing-row-group"> <div class="devsite-landing-row-item-body"> <h4 sticky-toc id="shape" data-text="Shape" tabindex="-1">Shape</h4> <div class="devsite-landing-row-item-description-content"> <p> With <code translate="no" dir="ltr">Shape</code>you can add the final touches. First, wrap the message body text around a <a href="/reference/kotlin/androidx/compose/material/package-summary#Surface(androidx.compose.ui.Modifier,androidx.compose.ui.graphics.Shape,androidx.compose.ui.graphics.Color,androidx.compose.ui.graphics.Color,androidx.compose.foundation.BorderStroke,androidx.compose.ui.unit.Dp,kotlin.Function0)"> <code translate="no" dir="ltr">Surface</code></a> composable. Doing so allows customizing the message body's shape and elevation. Padding is also added to the message for a better layout. </p> </div> </div> <div class="dac-step-preview-mobile"> <devsite-code dark-code class="dac-tutorial-code"> <pre is-upgraded class="prettyprint lang-kotlin dac-compose-snippet" translate="no" dir="ltr"> // ... <strong>import androidx.compose.material3.Surface</strong> @Composable fun MessageCard(msg: Message) { Row(modifier = Modifier.padding(all = 8.dp)) { Image( painter = painterResource(R.drawable.profile_picture), contentDescription = null, modifier = Modifier .size(40.dp) .clip(CircleShape) .border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape) ) Spacer(modifier = Modifier.width(8.dp)) Column { Text( text = msg.author, color = MaterialTheme.colorScheme.secondary, style = MaterialTheme.typography.titleSmall ) Spacer(modifier = Modifier.height(4.dp)) <strong>Surface(shape = MaterialTheme.shapes.medium, shadowElevation = 1.dp) {</strong> Text( text = msg.body, <strong>modifier = Modifier.padding(all = 4.dp),</strong> style = MaterialTheme.typography.bodyMedium ) <strong>}</strong> } } } </pre> </devsite-code> <div class="dac-preview-toggle-wrapper"> <div class="dac-preview-toggle show">show preview</div> <div class="dac-preview-toggle hide">hide preview</div> <img alt class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson3-05.png"> </div> </div> </div> </section> <section id="tut-step-5" class="devsite-landing-row"> <div class="devsite-landing-row-group"> <div class="devsite-landing-row-item-body"> <h4 sticky-toc id="enable-dark-theme" data-text="Enable dark theme" tabindex="-1">Enable dark theme</h4> <div class="devsite-landing-row-item-description-content"> <p> <a href="https://developer.android.com/guide/topics/ui/look-and-feel/darktheme">Dark theme</a> (or night mode) can be enabled to avoid a bright display especially at night, or simply to save the device battery. Thanks to the Material Design support, Jetpack Compose can handle the dark theme by default. Having used Material Design colors, text and backgrounds will automatically adapt to the dark background. </p> <p> You can create multiple previews in your file as separate functions, or add multiple annotations to the same function. </p> <p> Add a new preview annotation and enable night mode. </p> </div> </div> <div class="dac-step-preview-mobile"> <devsite-code dark-code class="dac-tutorial-code"> <pre is-upgraded class="prettyprint lang-kotlin dac-compose-snippet" translate="no" dir="ltr"> // ... <strong>import android.content.res.Configuration @Preview(name = "Light Mode") @Preview( uiMode = Configuration.UI_MODE_NIGHT_YES, showBackground = true, name = "Dark Mode" )</strong> @Composable fun PreviewMessageCard() { ComposeTutorialTheme { Surface { MessageCard( msg = Message("Lexi", "Hey, take a look at Jetpack Compose, it's great!") ) } } } </pre> </devsite-code> <div class="dac-preview-toggle-wrapper"> <div class="dac-preview-toggle show">show preview</div> <div class="dac-preview-toggle hide">hide preview</div> <img alt class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson3-06.png"> </div> </div> </div> </section> <section id="tut-step-6" class="devsite-landing-row"> <div class="devsite-landing-row-group"> <div class="devsite-landing-row-item-body"> <div class="devsite-landing-row-item-description-content"> <p> Color choices for the light and dark themes are defined in the IDE-generated <code translate="no" dir="ltr">Theme.kt</code> file. </p> <p> So far, you've created a message UI element that displays an image and two texts with different styles, and it looks good both in light and dark themes! </p> </div> </div> <div class="dac-step-preview-mobile"> <devsite-code dark-code class="dac-tutorial-code"> <pre is-upgraded class="prettyprint lang-kotlin dac-compose-snippet" translate="no" dir="ltr"> // ... <strong>import android.content.res.Configuration @Preview(name = "Light Mode") @Preview( uiMode = Configuration.UI_MODE_NIGHT_YES, showBackground = true, name = "Dark Mode" )</strong> @Composable fun PreviewMessageCard() { ComposeTutorialTheme { Surface { MessageCard( msg = Message("Lexi", "Hey, take a look at Jetpack Compose, it's great!") ) } } } </pre> </devsite-code> <div class="dac-preview-toggle-wrapper"> <div class="dac-preview-toggle show">show preview</div> <div class="dac-preview-toggle hide">hide preview</div> <img alt class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson3-06.png"> </div> </div> </div> </section> </div> <!-- preview assets --> <div class="dac-preview-wrapper"> <div id="tut-step-1-preview" class="dac-step-preview active"> <devsite-code dark-code class="dac-tutorial-code"> <pre is-upgraded class="prettyprint lang-kotlin dac-compose-snippet" translate="no" dir="ltr"> // ... class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) <strong>setContent { ComposeTutorialTheme { Surface(modifier = Modifier.fillMaxSize()) { MessageCard(Message("Android", "Jetpack Compose")) } } }</strong> } } <strong>@Preview @Composable fun PreviewMessageCard() { ComposeTutorialTheme { Surface { MessageCard( msg = Message("Lexi", "Take a look at Jetpack Compose, it's great!") ) } } }</strong> </pre> </devsite-code> <div class="dac-preview-toggle-wrapper"> <div class="dac-preview-toggle show">show preview</div> <div class="dac-preview-toggle hide">hide preview</div> <img alt class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson3-02.png"> </div> </div> <div id="tut-step-2-preview" class="dac-step-preview"> <devsite-code dark-code class="dac-tutorial-code"> <pre is-upgraded class="prettyprint lang-kotlin dac-compose-snippet" translate="no" dir="ltr"> // ... <strong>import androidx.compose.foundation.border import androidx.compose.material3.MaterialTheme</strong> @Composable fun MessageCard(msg: Message) { Row(modifier = Modifier.padding(all = 8.dp)) { Image( painter = painterResource(R.drawable.profile_picture), contentDescription = null, modifier = Modifier .size(40.dp) .clip(CircleShape) <strong>.border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape)</strong> ) Spacer(modifier = Modifier.width(8.dp)) Column { <strong>Text( text = msg.author, color = MaterialTheme.colorScheme.secondary )</strong> Spacer(modifier = Modifier.height(4.dp)) Text(text = msg.body) } } } </pre> </devsite-code> <div class="dac-preview-toggle-wrapper"> <div class="dac-preview-toggle show">show preview</div> <div class="dac-preview-toggle hide">hide preview</div> <img alt class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson3-03.png"> </div> </div> <div id="tut-step-3-preview" class="dac-step-preview"> <devsite-code dark-code class="dac-tutorial-code"> <pre is-upgraded class="prettyprint lang-kotlin dac-compose-snippet" translate="no" dir="ltr"> // ... @Composable fun MessageCard(msg: Message) { Row(modifier = Modifier.padding(all = 8.dp)) { Image( painter = painterResource(R.drawable.profile_picture), contentDescription = null, modifier = Modifier .size(40.dp) .clip(CircleShape) .border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape) ) Spacer(modifier = Modifier.width(8.dp)) Column { Text( text = msg.author, color = MaterialTheme.colorScheme.secondary, <strong>style = MaterialTheme.typography.titleSmall</strong> ) Spacer(modifier = Modifier.height(4.dp)) Text( text = msg.body, <strong>style = MaterialTheme.typography.bodyMedium</strong> ) } } } </pre> </devsite-code> <div class="dac-preview-toggle-wrapper"> <div class="dac-preview-toggle show">show preview</div> <div class="dac-preview-toggle hide">hide preview</div> <img alt class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson3-04.png"> </div> </div> <div id="tut-step-4-preview" class="dac-step-preview"> <devsite-code dark-code class="dac-tutorial-code"> <pre is-upgraded class="prettyprint lang-kotlin dac-compose-snippet" translate="no" dir="ltr"> // ... <strong>import androidx.compose.material3.Surface</strong> @Composable fun MessageCard(msg: Message) { Row(modifier = Modifier.padding(all = 8.dp)) { Image( painter = painterResource(R.drawable.profile_picture), contentDescription = null, modifier = Modifier .size(40.dp) .clip(CircleShape) .border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape) ) Spacer(modifier = Modifier.width(8.dp)) Column { Text( text = msg.author, color = MaterialTheme.colorScheme.secondary, style = MaterialTheme.typography.titleSmall ) Spacer(modifier = Modifier.height(4.dp)) <strong>Surface(shape = MaterialTheme.shapes.medium, shadowElevation = 1.dp) {</strong> Text( text = msg.body, <strong>modifier = Modifier.padding(all = 4.dp),</strong> style = MaterialTheme.typography.bodyMedium ) <strong>}</strong> } } } </pre> </devsite-code> <div class="dac-preview-toggle-wrapper"> <div class="dac-preview-toggle show">show preview</div> <div class="dac-preview-toggle hide">hide preview</div> <img alt class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson3-05.png"> </div> </div> <div id="tut-step-5-preview" class="dac-step-preview"> <devsite-code dark-code class="dac-tutorial-code"> <pre is-upgraded class="prettyprint lang-kotlin dac-compose-snippet" translate="no" dir="ltr"> // ... <strong>import android.content.res.Configuration @Preview(name = "Light Mode") @Preview( uiMode = Configuration.UI_MODE_NIGHT_YES, showBackground = true, name = "Dark Mode" )</strong> @Composable fun PreviewMessageCard() { ComposeTutorialTheme { Surface { MessageCard( msg = Message("Lexi", "Hey, take a look at Jetpack Compose, it's great!") ) } } } </pre> </devsite-code> <div class="dac-preview-toggle-wrapper"> <div class="dac-preview-toggle show">show preview</div> <div class="dac-preview-toggle hide">hide preview</div> <img alt class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson3-06.png"> </div> </div> <div id="tut-step-6-preview" class="dac-step-preview"> <div class="dac-preview-screenshot"> <img alt class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson3-07.png"> <figure> Preview showing both light and dark themed composables. </figure> </div> </div> </div> </div> </android-sticky-lesson> <div class="dac-tutorial-lesson-intro dac-indent"> <a href="#top_of_page"><div class="dac-nav-top"></div></a> <h2 sticky-toc sticky-toc-text="4: Lists and animations" id="lesson-4:-lists-and-animations" data-text="Lesson 4: Lists and animations" tabindex="-1">Lesson 4: Lists and animations</h2> <p> Lists and animations are everywhere in apps. In this lesson, you will learn how Compose makes it easy to create lists and fun to add animations. </p> <div class="dac-tutorial-lesson-intro-asset"> <img alt src="/static/develop/ui/compose/images/compose-tutorial/lesson4-01.svg"> </div> </div> <android-sticky-lesson lesson-id="4" step-ids="tut-step-1,tut-step-2,tut-step-3"> <!-- Please do not remove wrapping div's --> <div class="dac-lesson-wrapper"> <div class="dac-step-wrapper"> <!-- steps --> <section id="tut-step-1" class="devsite-landing-row"> <div class="devsite-landing-row-group"> <div class="devsite-landing-row-item-body"> <h4 sticky-toc id="create-a-list-of-messages" data-text="Create a list of messages" tabindex="-1">Create a list of messages</h4> <div class="devsite-landing-row-item-description-content"> <p> A chat with one message feels a bit lonely, so we are going to change the conversation to have more than one message. You'll need to create a <code translate="no" dir="ltr">Conversation</code> function that will show multiple messages. For this use case, use Compose’s <a href="/reference/kotlin/androidx/compose/foundation/lazy/package-summary#LazyColumn(androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.LazyListState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.ui.Alignment.Horizontal,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)"> <code translate="no" dir="ltr">LazyColumn</code></a> and <a href="/reference/kotlin/androidx/compose/foundation/lazy/package-summary#LazyRow(androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.LazyListState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Horizontal,androidx.compose.ui.Alignment.Vertical,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)"> <code translate="no" dir="ltr">LazyRow</code></a>. These composables render only the elements that are visible on screen, so they are designed to be very efficient for long lists. </p> <p> In this code snippet, you can see that <code translate="no" dir="ltr">LazyColumn</code> has an <code translate="no" dir="ltr">items</code> child. It takes a <code translate="no" dir="ltr">List</code> as a parameter and its lambda receives a parameter we’ve named <code translate="no" dir="ltr">message</code> (we could have named it whatever we want) which is an instance of <code translate="no" dir="ltr">Message</code>. In short, this lambda is called for each item of the provided <code translate="no" dir="ltr">List</code>. Copy the <a href="/static/develop/ui/compose/tutorial/lessons/lesson-4/steps/code/SampleData.kt">sample dataset</a> into your project to help bootstrap the conversation quickly. </p> </div> </div> <div class="dac-step-preview-mobile"> <devsite-code dark-code class="dac-tutorial-code"> <pre is-upgraded class="prettyprint lang-kotlin dac-compose-snippet" translate="no" dir="ltr"> // ... <strong>import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items @Composable fun Conversation(messages: List<Message>) { LazyColumn { items(messages) { message -> MessageCard(message) } } } @Preview @Composable fun PreviewConversation() { ComposeTutorialTheme { Conversation(SampleData.conversationSample) } }</strong> </pre> </devsite-code> <div class="dac-preview-toggle-wrapper"> <div class="dac-preview-toggle show">show preview</div> <div class="dac-preview-toggle hide">hide preview</div> <img alt class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson4-02.png"> </div> </div> </div> </section> <section id="tut-step-2" class="devsite-landing-row"> <div class="devsite-landing-row-group"> <div class="devsite-landing-row-item-body"> <h4 sticky-toc id="animate-messages-while-expanding" data-text="Animate messages while expanding" tabindex="-1">Animate messages while expanding</h4> <div class="devsite-landing-row-item-description-content"> <p> The conversation is getting more interesting. It's time to play with animations! You will add the ability to expand a message to show a longer one, animating both the content size and the background color. To store this local UI state, you need to keep track of whether a message has been expanded or not. To keep track of this state change, you have to use the functions <code translate="no" dir="ltr">remember</code> and <code translate="no" dir="ltr">mutableStateOf</code>. </p> <p> Composable functions can store local state in memory by using <code translate="no" dir="ltr">remember</code>, and track changes to the value passed to <code translate="no" dir="ltr">mutableStateOf</code>. Composables (and their children) using this state will get redrawn automatically when the value is updated. This is called <a href="https://developer.android.com/develop/ui/compose/mental-model#recomposition">recomposition</a>. </p> <p> By using Compose’s state APIs like <code translate="no" dir="ltr">remember</code> and <code translate="no" dir="ltr">mutableStateOf</code>, any changes to state automatically update the UI. </p> <p class="note"> <strong>Note:</strong> You need to add the following imports to correctly use Kotlin's delegated property syntax (the <code translate="no" dir="ltr">by</code> keyword). Alt+Enter or Option+Enter adds them for you.<br> <code translate="no" dir="ltr"> import androidx.compose.runtime.getValue import androidx.compose.runtime.setValue </code> </p> </div> </div> <div class="dac-step-preview-mobile"> <devsite-code dark-code class="dac-tutorial-code"> <pre is-upgraded class="prettyprint lang-kotlin dac-compose-snippet" translate="no" dir="ltr"> // ... <strong>import androidx.compose.foundation.clickable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue</strong> class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { ComposeTutorialTheme { <strong>Conversation(SampleData.conversationSample)</strong> } } } } @Composable fun MessageCard(msg: Message) { Row(modifier = Modifier.padding(all = 8.dp)) { Image( painter = painterResource(R.drawable.profile_picture), contentDescription = null, modifier = Modifier .size(40.dp) .clip(CircleShape) .border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape) ) Spacer(modifier = Modifier.width(8.dp)) <strong>// We keep track if the message is expanded or not in this // variable var isExpanded by remember { mutableStateOf(false) } // We toggle the isExpanded variable when we click on this Column Column(modifier = Modifier.clickable { isExpanded = !isExpanded }) {</strong> Text( text = msg.author, color = MaterialTheme.colorScheme.secondary, style = MaterialTheme.typography.titleSmall ) Spacer(modifier = Modifier.height(4.dp)) Surface( shape = MaterialTheme.shapes.medium, shadowElevation = 1.dp, ) { <strong>Text( text = msg.body, modifier = Modifier.padding(all = 4.dp), // If the message is expanded, we display all its content // otherwise we only display the first line maxLines = if (isExpanded) Int.MAX_VALUE else 1, style = MaterialTheme.typography.bodyMedium )</strong> } <strong>}</strong> } } </pre> </devsite-code> <div class="dac-preview-toggle-wrapper"> <div class="dac-preview-toggle show">show preview</div> <div class="dac-preview-toggle hide">hide preview</div> <div class="dac-preview-phone"> <div class="dac-dropshadow"> <video autoplay muted loop class="block dac-preview-video"> <source src="https://storage.googleapis.com/android-stories/compose/lesson4-03_m3.mp4" type="video/mp4"> </video> </div> </div> </div> </div> </div> </section> <section id="tut-step-3" class="devsite-landing-row"> <div class="devsite-landing-row-group"> <div class="devsite-landing-row-item-body"> <div class="devsite-landing-row-item-description-content"> <p> Now you can change the background of the message content based on <code translate="no" dir="ltr">isExpanded</code> when we click on a message. You will use the <code translate="no" dir="ltr">clickable</code> modifier to handle click events on the composable. Instead of just toggling the background color of the <code translate="no" dir="ltr">Surface</code>, you will animate the background color by gradually modifying its value from <code translate="no" dir="ltr">MaterialTheme.colorScheme.surface</code> to <code translate="no" dir="ltr">MaterialTheme.colorScheme.primary</code> and vice versa. To do so, you will use the <code translate="no" dir="ltr">animateColorAsState</code> function. Lastly, you will use the <code translate="no" dir="ltr">animateContentSize</code> modifier to animate the message container size smoothly: </p> </div> </div> <div class="dac-step-preview-mobile"> <devsite-code dark-code class="dac-tutorial-code"> <pre is-upgraded class="prettyprint lang-kotlin dac-compose-snippet" translate="no" dir="ltr"> // ... <strong>import androidx.compose.animation.animateColorAsState import androidx.compose.animation.animateContentSize</strong> @Composable fun MessageCard(msg: Message) { Row(modifier = Modifier.padding(all = 8.dp)) { Image( painter = painterResource(R.drawable.profile_picture), contentDescription = null, modifier = Modifier .size(40.dp) .clip(CircleShape) .border(1.5.dp, MaterialTheme.colorScheme.secondary, CircleShape) ) Spacer(modifier = Modifier.width(8.dp)) // We keep track if the message is expanded or not in this // variable var isExpanded by remember { mutableStateOf(false) } <strong>// surfaceColor will be updated gradually from one color to the other val surfaceColor by animateColorAsState( if (isExpanded) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.surface, )</strong> // We toggle the isExpanded variable when we click on this Column Column(modifier = Modifier.clickable { isExpanded = !isExpanded }) { Text( text = msg.author, color = MaterialTheme.colorScheme.secondary, style = MaterialTheme.typography.titleSmall ) Spacer(modifier = Modifier.height(4.dp)) Surface( shape = MaterialTheme.shapes.medium, shadowElevation = 1.dp, <strong>// surfaceColor color will be changing gradually from primary to surface color = surfaceColor, // animateContentSize will change the Surface size gradually modifier = Modifier.animateContentSize().padding(1.dp)</strong> ) { Text( text = msg.body, modifier = Modifier.padding(all = 4.dp), // If the message is expanded, we display all its content // otherwise we only display the first line maxLines = if (isExpanded) Int.MAX_VALUE else 1, style = MaterialTheme.typography.bodyMedium ) } } } } </pre> </devsite-code> <div class="dac-preview-toggle-wrapper"> <div class="dac-preview-toggle show">show preview</div> <div class="dac-preview-toggle hide">hide preview</div> <div class="dac-preview-phone"> <div class="dac-dropshadow"> <video autoplay muted loop class="block dac-preview-video"> <source src="https://storage.googleapis.com/android-stories/compose/lesson4-04_m3.mp4" type="video/mp4"> </video> </div> </div> </div> </div> </div> </section> </div> <!-- preview assets --> <div class="dac-preview-wrapper"> <div id="tut-step-1-preview" class="dac-step-preview active"> <devsite-code dark-code class="dac-tutorial-code"> <pre is-upgraded class="prettyprint lang-kotlin dac-compose-snippet" translate="no" dir="ltr"> // ... <strong>import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items @Composable fun Conversation(messages: List<Message>) { LazyColumn { items(messages) { message -> MessageCard(message) } } } @Preview @Composable fun PreviewConversation() { ComposeTutorialTheme { Conversation(SampleData.conversationSample) } }</strong> </pre> </devsite-code> <div class="dac-preview-toggle-wrapper"> <div class="dac-preview-toggle show">show preview</div> <div class="dac-preview-toggle hide">hide preview</div> <img alt class="dac-preview-phone" src="/static/develop/ui/compose/images/compose-tutorial/lesson4-02.png"> </div> </div> <div id="tut-step-2-preview" class="dac-step-preview"> <devsite-code dark-code class="dac-tutorial-code"> <pre is-upgraded class="prettyprint lang-kotlin dac-compose-snippet" translate="no" dir="ltr"> // ... <strong>import androidx.compose.foundation.clickable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue</strong> class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { ComposeTutorialTheme { <strong>Conversation(SampleData.conversationSample)</strong> } } } } @Composable fun MessageCard(msg: Message) { Row(modifier = Modifier.padding(all = 8.dp)) { Image( painter = painterResource(R.drawable.profile_picture), contentDescription = null, modifier = Modifier .size(40.dp) .clip(CircleShape) .border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape) ) Spacer(modifier = Modifier.width(8.dp)) <strong>// We keep track if the message is expanded or not in this // variable var isExpanded by remember { mutableStateOf(false) } // We toggle the isExpanded variable when we click on this Column Column(modifier = Modifier.clickable { isExpanded = !isExpanded }) {</strong> Text( text = msg.author, color = MaterialTheme.colorScheme.secondary, style = MaterialTheme.typography.titleSmall ) Spacer(modifier = Modifier.height(4.dp)) Surface( shape = MaterialTheme.shapes.medium, shadowElevation = 1.dp, ) { <strong>Text( text = msg.body, modifier = Modifier.padding(all = 4.dp), // If the message is expanded, we display all its content // otherwise we only display the first line maxLines = if (isExpanded) Int.MAX_VALUE else 1, style = MaterialTheme.typography.bodyMedium )</strong> } <strong>}</strong> } } </pre> </devsite-code> <div class="dac-preview-toggle-wrapper"> <div class="dac-preview-toggle show">show preview</div> <div class="dac-preview-toggle hide">hide preview</div> <div class="dac-preview-phone"> <div class="dac-dropshadow"> <video autoplay muted loop class="block dac-preview-video"> <source src="https://storage.googleapis.com/android-stories/compose/lesson4-03_m3.mp4" type="video/mp4"> </video> </div> </div> </div> </div> <div id="tut-step-3-preview" class="dac-step-preview"> <devsite-code dark-code class="dac-tutorial-code"> <pre is-upgraded class="prettyprint lang-kotlin dac-compose-snippet" translate="no" dir="ltr"> // ... <strong>import androidx.compose.animation.animateColorAsState import androidx.compose.animation.animateContentSize</strong> @Composable fun MessageCard(msg: Message) { Row(modifier = Modifier.padding(all = 8.dp)) { Image( painter = painterResource(R.drawable.profile_picture), contentDescription = null, modifier = Modifier .size(40.dp) .clip(CircleShape) .border(1.5.dp, MaterialTheme.colorScheme.secondary, CircleShape) ) Spacer(modifier = Modifier.width(8.dp)) // We keep track if the message is expanded or not in this // variable var isExpanded by remember { mutableStateOf(false) } <strong>// surfaceColor will be updated gradually from one color to the other val surfaceColor by animateColorAsState( if (isExpanded) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.surface, )</strong> // We toggle the isExpanded variable when we click on this Column Column(modifier = Modifier.clickable { isExpanded = !isExpanded }) { Text( text = msg.author, color = MaterialTheme.colorScheme.secondary, style = MaterialTheme.typography.titleSmall ) Spacer(modifier = Modifier.height(4.dp)) Surface( shape = MaterialTheme.shapes.medium, shadowElevation = 1.dp, <strong>// surfaceColor color will be changing gradually from primary to surface color = surfaceColor, // animateContentSize will change the Surface size gradually modifier = Modifier.animateContentSize().padding(1.dp)</strong> ) { Text( text = msg.body, modifier = Modifier.padding(all = 4.dp), // If the message is expanded, we display all its content // otherwise we only display the first line maxLines = if (isExpanded) Int.MAX_VALUE else 1, style = MaterialTheme.typography.bodyMedium ) } } } } </pre> </devsite-code> <div class="dac-preview-toggle-wrapper"> <div class="dac-preview-toggle show">show preview</div> <div class="dac-preview-toggle hide">hide preview</div> <div class="dac-preview-phone"> <div class="dac-dropshadow"> <video autoplay muted loop class="block dac-preview-video"> <source src="https://storage.googleapis.com/android-stories/compose/lesson4-04_m3.mp4" type="video/mp4"> </video> </div> </div> </div> </div> </div> </div> </android-sticky-lesson> </div> <android-sticky-toc sticky class="android-sticky-toc" eyebrow-text="Tutorial" back-to-top-text="Learning the basics of Compose"> </android-sticky-toc> </section> </div> </div> </section> <section class="devsite-landing-row devsite-landing-row-1-up devsite-landing-row-padding-medium dac-tutorial-done dac-bullet-list" header-position="top" > <div class="devsite-landing-row-inner"> <div class="devsite-landing-row-html"> <android-sticky-lesson lesson-id="next-steps"> <div class="section-container dac-compose-grid-container dac-compose-grid-container--no-padding"> <div class="lesson-intro"> <section class="devsite-landing-row devsite-landing-row-1-up android-row-padding-none"> <div class="devsite-landing-row-html dac-tutorial-done dac-bullet-list dac-body-one-light"> <h2 class="all-done" id="next-steps" data-text="Next steps" tabindex="-1">Next steps</h2> <p> Congratulations, you’ve finished the Compose tutorial! You’ve built a simple chat screen efficiently showing a list of expandable & animated messages containing an image and texts, designed using Material Design principles with a dark theme included and previews—all in <strong>under 100 lines of code!</strong></p> <p>Here’s what you've learned so far:</p> <ul class="devsite-landing-row-item-list"> <li class="devsite-landing-row-item-list-item"> Defining composable functions </li> <li class="devsite-landing-row-item-list-item"> Adding different elements in your composable </li> <li class="devsite-landing-row-item-list-item"> Structuring your UI component using layout composables </li> <li class="devsite-landing-row-item-list-item"> Extending composables by using modifiers </li> <li class="devsite-landing-row-item-list-item"> Creating an efficient list </li> <li class="devsite-landing-row-item-list-item"> Keeping track of state and modifying it </li> <li class="devsite-landing-row-item-list-item"> Adding user interaction on a composable </li> <li class="devsite-landing-row-item-list-item"> Animating messages while expanding them </li> </ul> <p> If you want to dig deeper on some of these steps, explore the resources below. </p> </div> </section> </div> </div> </android-sticky-lesson> </div> </div> </section> <section class="devsite-landing-row devsite-landing-row-2-up" header-position="top" > <div class="devsite-landing-row-inner"> <header class="devsite-landing-row-header" > <div class="devsite-landing-row-header-text"> <h2 id="next-steps" data-text="Next steps" tabindex="0"> Next steps </h2> </div> </header> <div class="devsite-landing-row-group"> <div class="devsite-landing-row-item devsite-landing-row-item-no-media android-item-background-blue-100 android-item-dark-background-blue-700" description-position="bottom" > <div class="devsite-landing-row-item-description" > <div class="devsite-landing-row-item-body"> <div class="devsite-landing-row-item-labels"> <span class=" " >Setup</span> </div> <h3 id="get-set-up" data-text="Get set up" class="hide-from-toc no-link" tabindex="0"> <a href="https://developer.android.com/develop/ui/compose/setup"> Get set up </a> </h3> <div class="devsite-landing-row-item-description-content"> Now that you've finished the Compose tutorial, you're ready to start building with Compose. </div> <div class="devsite-landing-row-item-buttons"> <a href="https://developer.android.com/develop/ui/compose/setup" class="button button-primary " >Create a new app</a> <a href="https://developer.android.com/develop/ui/compose/setup#setup-compose" class="button " >Add to an existing app</a> </div> </div> </div> </div> <div class="devsite-landing-row-item devsite-landing-row-item-no-media android-item-background-blue-100 android-item-dark-background-blue-700" description-position="bottom" > <div class="devsite-landing-row-item-description" > <div class="devsite-landing-row-item-body"> <div class="devsite-landing-row-item-labels"> <span class=" " >Pathway</span> </div> <h3 id="continue-learning" data-text="Continue learning" class="hide-from-toc no-link" tabindex="0"> <a href="https://developer.android.com/courses/pathways/compose"> Continue learning </a> </h3> <div class="devsite-landing-row-item-description-content"> Check out our curated pathway of codelabs and videos that will help you learn and master Jetpack Compose. </div> <div class="devsite-landing-row-item-buttons"> <a href="https://developer.android.com/courses/pathways/compose" class="button " >Start course</a> </div> </div> </div> </div> </div> </div> </section> <devsite-hats-survey class="nocontent" hats-id="m71UDKaJT0kxBYCLVTd0U6CJGcqa" listnr-id="5207477"></devsite-hats-survey> </div> <div class="devsite-floating-action-buttons"> </div> </article> <devsite-notification > </devsite-notification> <div class="devsite-content-data"> <template class="devsite-content-data-template"> [[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],[],[],[]] </template> </div> </devsite-content> </main> <devsite-footer-promos class="devsite-footer"> <nav class="devsite-footer-promos nocontent" aria-label="Promotions"> <ul class="devsite-footer-promos-list"> <li class="devsite-footer-promo"> <a href="//x.com/AndroidDev" class="devsite-footer-promo-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer X Promo" > <picture> <source class="devsite-dark-theme" srcset="https://developer.android.com/_static/android/images/logo-x_dt.svg" media="(prefers-color-scheme: dark)" loading="lazy" alt="X"> <img class="devsite-footer-promo-icon" src="/_static/android/images/logo-x.svg" loading="lazy" alt="X"> </picture> <span class="devsite-footer-promo-label"> X </span> </a> <div class="devsite-footer-promo-description">Follow @AndroidDev on X</div> </li> <li class="devsite-footer-promo"> <a href="//www.youtube.com/user/androiddevelopers" class="devsite-footer-promo-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer YouTube Promo" > <picture> <source class="devsite-dark-theme" srcset="https://developer.android.com/_static/android/images/logo-youtube_dt.svg" media="(prefers-color-scheme: dark)" loading="lazy" alt="YouTube"> <img class="devsite-footer-promo-icon" src="//www.gstatic.com/images/icons/material/product/2x/youtube_48dp.png" loading="lazy" alt="YouTube"> </picture> <span class="devsite-footer-promo-label"> YouTube </span> </a> <div class="devsite-footer-promo-description">Check out Android Developers on YouTube</div> </li> <li class="devsite-footer-promo"> <a href="//www.linkedin.com/showcase/androiddev" class="devsite-footer-promo-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer LinkedIn Promo" > <picture> <source class="devsite-dark-theme" srcset="https://developer.android.com/_static/android/images/logo-linkedin_dt.svg" media="(prefers-color-scheme: dark)" loading="lazy" alt="LinkedIn"> <img class="devsite-footer-promo-icon" src="/_static/android/images/logo-linkedin.svg" loading="lazy" alt="LinkedIn"> </picture> <span class="devsite-footer-promo-label"> LinkedIn </span> </a> <div class="devsite-footer-promo-description">Connect with the Android Developers community on LinkedIn</div> </li> </ul> </nav> </devsite-footer-promos> <devsite-footer-linkboxes class="devsite-footer"> <nav class="devsite-footer-linkboxes nocontent" aria-label="Footer links"> <ul class="devsite-footer-linkboxes-list"> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">More Android</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="//www.android.com" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" > Android </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//www.android.com/enterprise/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" > Android for Enterprise </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//www.android.com/security-center/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 3)" > Security </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//source.android.com" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 4)" > Source </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/news" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 5)" > News </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//android-developers.googleblog.com/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 6)" > Blog </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/podcasts" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 7)" > Podcasts </a> </li> </ul> </li> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">Discover</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="/games" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" > Gaming </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/ml" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" > Machine Learning </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/health-and-fitness" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 3)" > Health & Fitness </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/media" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 4)" > Camera & Media </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/privacy" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 5)" > Privacy </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/training/connectivity/5g" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 6)" > 5G </a> </li> </ul> </li> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">Android Devices</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="/large-screens" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" > Large screens </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/wear" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" > Wear OS </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/chrome-os" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 3)" > ChromeOS devices </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/cars" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 4)" > Android for cars </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/tv" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 5)" > Android TV </a> </li> </ul> </li> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">Releases</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="/about/versions/15" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" > Android 15 </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/about/versions/14" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" > Android 14 </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/about/versions/13" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 3)" > Android 13 </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/about/versions/12" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 4)" > Android 12 </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/about/versions/11" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 5)" > Android 11 </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/about/versions/10" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 6)" > Android 10 </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/about/versions/pie" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 7)" > Pie </a> </li> </ul> </li> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">Documentation and Downloads</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="/studio/intro" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" > Android Studio guide </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/guide" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" > Developers guides </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/reference" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 3)" > API reference </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/studio" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 4)" > Download Studio </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/ndk" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 5)" > Android NDK </a> </li> </ul> </li> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">Support</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="//issuetracker.google.com/issues/new?component=190923&template=841312" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" > Report platform bug </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//issuetracker.google.com/issues/new?component=192697" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" > Report documentation bug </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//support.google.com/googleplay/android-developer" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 3)" > Google Play support </a> </li> <li class="devsite-footer-linkbox-item"> <a href="https://g.co/userresearch/androiddeveloperfooter" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 4)" > Join research studies </a> </li> </ul> </li> </ul> </nav> </devsite-footer-linkboxes> <devsite-footer-utility class="devsite-footer"> <div class="devsite-footer-utility nocontent"> <nav class="devsite-footer-sites" aria-label="Other Google Developers websites"> <a href="https://developers.google.com/" class="devsite-footer-sites-logo-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Google Developers Link"> <picture> <source srcset="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/android/images/lockup-google-for-developers-dark-theme.svg" media="(prefers-color-scheme: none)" class="devsite-dark-theme" loading="lazy" alt="Google Developers"> <img class="devsite-footer-sites-logo" src="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/android/images/lockup-google-for-developers.svg" loading="lazy" alt="Google Developers"> </picture> </a> <ul class="devsite-footer-sites-list"> <li class="devsite-footer-sites-item"> <a href="//developer.android.com" class="devsite-footer-sites-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Android Link" > Android </a> </li> <li class="devsite-footer-sites-item"> <a href="//developer.chrome.com/home" class="devsite-footer-sites-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Chrome Link" > Chrome </a> </li> <li class="devsite-footer-sites-item"> <a href="//firebase.google.com" class="devsite-footer-sites-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Firebase Link" > Firebase </a> </li> <li class="devsite-footer-sites-item"> <a href="//cloud.google.com" class="devsite-footer-sites-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Google Cloud Platform Link" > Google Cloud Platform </a> </li> <li class="devsite-footer-sites-item"> <a href="//developers.google.com/products/" class="devsite-footer-sites-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer All products Link" > All products </a> </li> </ul> </nav> <nav class="devsite-footer-utility-links" aria-label="Utility links"> <ul class="devsite-footer-utility-list"> <li class="devsite-footer-utility-item "> <a class="devsite-footer-utility-link gc-analytics-event" href="//policies.google.com/privacy" data-category="Site-Wide Custom Events" data-label="Footer Privacy link" > Privacy </a> </li> <li class="devsite-footer-utility-item "> <a class="devsite-footer-utility-link gc-analytics-event" href="/license" data-category="Site-Wide Custom Events" data-label="Footer License link" > License </a> </li> <li class="devsite-footer-utility-item "> <a class="devsite-footer-utility-link gc-analytics-event" href="/distribute/marketing-tools/brand-guidelines" data-category="Site-Wide Custom Events" data-label="Footer Brand guidelines link" > Brand guidelines </a> </li> <li class="devsite-footer-utility-item glue-cookie-notification-bar-control"> <a class="devsite-footer-utility-link gc-analytics-event" href="#" data-category="Site-Wide Custom Events" data-label="Footer Manage cookies link" aria-hidden="true" > Manage cookies </a> </li> <li class="devsite-footer-utility-item devsite-footer-utility-button"> <span class="devsite-footer-utility-description">Get news and tips by email</span> <a class="devsite-footer-utility-link gc-analytics-event" href="/updates" data-category="Site-Wide Custom Events" data-label="Footer Subscribe link" > Subscribe </a> </li> </ul> <devsite-language-selector> <ul role="presentation"> <li role="presentation"> <a role="menuitem" lang="en" >English</a> </li> <li role="presentation"> <a role="menuitem" lang="de" >Deutsch</a> </li> <li role="presentation"> <a role="menuitem" lang="es_419" >Español – América Latina</a> </li> <li role="presentation"> <a role="menuitem" lang="fr" >Français</a> </li> <li role="presentation"> <a role="menuitem" lang="id" >Indonesia</a> </li> <li role="presentation"> <a role="menuitem" lang="it" >Italiano</a> </li> <li role="presentation"> <a role="menuitem" lang="pl" >Polski</a> </li> <li role="presentation"> <a role="menuitem" lang="pt_br" >Português – Brasil</a> </li> <li role="presentation"> <a role="menuitem" lang="vi" >Tiếng Việt</a> </li> <li role="presentation"> <a role="menuitem" lang="tr" >Türkçe</a> </li> <li role="presentation"> <a role="menuitem" lang="ru" >Русский</a> </li> <li role="presentation"> <a role="menuitem" lang="he" >עברית</a> </li> <li role="presentation"> <a role="menuitem" lang="ar" >العربيّة</a> </li> <li role="presentation"> <a role="menuitem" lang="fa" >فارسی</a> </li> <li role="presentation"> <a role="menuitem" lang="hi" >हिंदी</a> </li> <li role="presentation"> <a role="menuitem" lang="bn" >বাংলা</a> </li> <li role="presentation"> <a role="menuitem" lang="th" >ภาษาไทย</a> </li> <li role="presentation"> <a role="menuitem" lang="zh_cn" >中文 – 简体</a> </li> <li role="presentation"> <a role="menuitem" lang="zh_tw" >中文 – 繁體</a> </li> <li role="presentation"> <a role="menuitem" lang="ja" >日本語</a> </li> <li role="presentation"> <a role="menuitem" lang="ko" >한국어</a> </li> </ul> </devsite-language-selector> </nav> </div> </devsite-footer-utility> <devsite-panel></devsite-panel> </section></section> <devsite-sitemask></devsite-sitemask> <devsite-snackbar></devsite-snackbar> <devsite-tooltip ></devsite-tooltip> <devsite-heading-link></devsite-heading-link> <devsite-analytics> <script type="application/json" analytics>[]</script> <script type="application/json" tag-management>{"at": "True", "ga4": [{"id": "G-QFRN08RN6E", "purpose": 0}], "ga4p": [{"id": "G-QFRN08RN6E", "purpose": 0}], "gtm": [{"id": "GTM-KMSWPCJ", "purpose": 0}], "parameters": {"internalUser": "False", "language": {"machineTranslated": "False", "requested": "en", "served": "en"}, "pageType": "article", "projectName": "Jetpack Compose", "signedIn": "False", "tenant": "android", "recommendations": {"sourcePage": "", "sourceType": 0, "sourceRank": 0, "sourceIdenticalDescriptions": 0, "sourceTitleWords": 0, "sourceDescriptionWords": 0, "experiment": ""}, "experiment": {"ids": ""}}}</script> </devsite-analytics> <devsite-badger></devsite-badger> <android-fully-clickable target=" .android-case-study .devsite-landing-row-item, .android-grouped-resources .devsite-landing-row-item, .android-grouped-resources-primary .devsite-landing-row-item, .android-grouped-resources-secondary .devsite-landing-row-item, .android-guide-cards .devsite-landing-row-item, .android-illustrated-resources-index .devsite-landing-row-item, .android-illustrated-resources-primary .devsite-landing-row-item, .android-illustrated-resources-secondary .devsite-landing-row-item, .android-illustrated-resources-secondary-small .devsite-landing-row-item, .android-illustrated-resources-tertiary .devsite-landing-row-item, .android-illustrated-resources-tertiary-small .devsite-landing-row-item, .android-promo .devsite-landing-row-item, .android-quick-link, .android-samples .devsite-card-wrapper, .fully-clickable" watch=".android-samples, devsite-content"></android-fully-clickable> <script nonce="ZcNdh0mQifAM6KhamHX0echCUtaTP4"> (function(d,e,v,s,i,t,E){d['GoogleDevelopersObject']=i; t=e.createElement(v);t.async=1;t.src=s;E=e.getElementsByTagName(v)[0]; E.parentNode.insertBefore(t,E);})(window, document, 'script', 'https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/android/js/app_loader.js', '[3,"en",null,"/js/devsite_app_module.js","https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625","https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/android","https://android-dot-devsite-v2-prod.appspot.com",1,null,["/_pwa/android/manifest.json","https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/images/video-placeholder.svg","https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/android/images/favicon.svg","https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/android/images/lockup.svg","https://fonts.googleapis.com/css?family=Google+Sans:400,500,600,700|Google+Sans+Text:400,400italic,500,500italic,600,600italic,700,700italic|Roboto+Mono:400,500,700&display=swap"],1,null,[1,6,8,12,14,17,21,25,50,52,63,70,75,76,80,87,91,92,93,97,98,100,101,102,103,104,105,107,108,109,110,112,113,116,117,118,120,122,124,125,126,127,129,130,131,132,133,134,135,136,138,140,141,147,148,149,151,152,156,157,158,159,161,163,164,168,169,170,179,180,182,183,186,191,193,196],"AIzaSyAP-jjEJBzmIyKR4F-3XITp8yM9T1gEEI8","AIzaSyB6xiKGDR5O3Ak2okS4rLkauxGUG7XP0hg","developer.android.com","AIzaSyAQk0fBONSGUqCNznf6Krs82Ap1-NV6J4o","AIzaSyCCxcqdrZ_7QMeLCRY20bh_SXdAYqy70KY",null,null,null,["CloudShell__cloud_code_overflow_menu","Cloud__enable_free_trial_server_call","Search__enable_ai_search_summaries","Search__enable_ai_eligibility_checks","MiscFeatureFlags__developers_footer_image","TpcFeatures__enable_required_headers","Profiles__enable_profile_collections","Search__enable_suggestions_from_borg","MiscFeatureFlags__enable_explain_this_code","Experiments__reqs_query_experiments","Profiles__enable_awarding_url","DevPro__enable_developer_subscriptions","MiscFeatureFlags__enable_project_variables","Profiles__enable_dashboard_curated_recommendations","Concierge__enable_pushui","Significatio__enable_by_tenant","Profiles__enable_completecodelab_endpoint","Search__enable_dynamic_content_confidential_banner","Cloud__enable_cloud_shell_fte_user_flow","Profiles__enable_recognition_badges","Cloud__enable_cloudx_experiment_ids","Cloud__enable_llm_concierge_chat","Profiles__enable_complete_playlist_endpoint","Cloud__enable_cloudx_ping","Search__enable_page_map","MiscFeatureFlags__developers_footer_dark_image","Analytics__enable_clearcut_logging","MiscFeatureFlags__enable_view_transitions","TpcFeatures__enable_mirror_tenant_redirects","CloudShell__cloud_shell_button","BookNav__enable_tenant_cache_key","EngEduTelemetry__enable_engedu_telemetry","Profiles__enable_page_saving","MiscFeatureFlags__enable_dark_theme","Profiles__enable_developer_profiles_callout","DevPro__enable_cloud_innovators_plus","Cloud__enable_cloud_facet_chat","Profiles__enable_release_notes_notifications","MiscFeatureFlags__enable_variable_operator","Profiles__enable_public_developer_profiles","MiscFeatureFlags__emergency_css","Profiles__require_profile_eligibility_for_signin","MiscFeatureFlags__enable_firebase_utm","Cloud__enable_legacy_calculator_redirect","Cloud__enable_cloud_dlp_service","Cloud__enable_cloud_shell"],null,null,"AIzaSyBLEMok-5suZ67qRPzx0qUtbnLmyT_kCVE","https://developerscontentserving-pa.googleapis.com","AIzaSyCM4QpTRSqP5qI4Dvjt4OAScIN8sOUlO-k","https://developerscontentsearch-pa.googleapis.com",2,4,null,"https://developerprofiles-pa.googleapis.com",[3,"android","Android Developers","developer.android.com",null,"android-dot-devsite-v2-prod.appspot.com",null,null,[null,1,null,null,null,null,null,null,null,null,null,[1],null,null,null,null,null,null,[1],[1,null,null,[1,20],"/recommendations"],null,null,null,[1,null,1],[1,1,null,1,1]],null,[18,null,null,null,null,null,"/images/lockup.svg","/images/touchicon-180.png",null,null,null,null,null,null,null,null,null,null,null,null,null,1,null,null,null,"/images/lockup-dark-theme.svg",[]],[],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[6,1,14,15,20,22,23,28,29,37,43],null,[[null,null,1],[1,1]],[[null,null,null,null,null,null,null,[["G-QFRN08RN6E"],null,null,[["G-QFRN08RN6E",1]]],null,null,null,null,1],null,[[1,1],[2,2]]],null,4,null,null,null,null,null,null,null,null,null,null,null,null,null,"android.devsite.google"],null,"pk_live_5170syrHvgGVmSx9sBrnWtA5luvk9BwnVcvIi7HizpwauFG96WedXsuXh790rtij9AmGllqPtMLfhe2RSwD6Pn38V00uBCydV4m"]') </script> <devsite-a11y-announce></devsite-a11y-announce> </body> </html>