Migration steps
To migrate
CoordinatorLayout to Scaffold, follow these steps:- In the snippet below, the
CoordinatorLayoutcontains anAppBarLayoutfor containing aToolBar, aViewPager, and aFloatingActionButton. Comment out theCoordinatorLayoutand its children from your UI hierarchy and add aComposeViewto replace it.
Note: Since
CoordinatorLayout is a ViewGroup, it's best to migrate all its child views to Compose at the same time or prior to this step, depending on your migration strategy. However, if you are unable to do so, you can add an AndroidView to use Views within Compose. See Using Views in Compose to learn more.- In your Fragment or Activity, obtain a reference to the
ComposeViewyou just added and call thesetContentmethod on it. In the body of the method, set aScaffoldas its content:
composeView.setContent { Scaffold(Modifier.fillMaxSize()) { contentPadding -> // Scaffold contents // ... } }
- In the content of your
Scaffold, add your screen's primary content within it. Because the primary content in the XML above is aViewPager2, we'll use aHorizontalPager, which is the Compose equivalent of it. Thecontentlambda of theScaffoldalso receives an instance ofPaddingValuesthat should be applied to the content root. You can useModifier.paddingto apply the samePaddingValuesto theHorizontalPager.
composeView.setContent { Scaffold(Modifier.fillMaxSize()) { contentPadding -> val pagerState = rememberPagerState { 10 } HorizontalPager( state = pagerState, modifier = Modifier.padding(contentPadding) ) { /* Page contents */ } } }
- Use other content slots that
Scaffoldprovides to add more screen elements and migrate remaining child Views. You can use thetopBarslot to add aTopAppBar, and thefloatingActionButtonslot to provide aFloatingActionButton.
composeView.setContent { Scaffold( Modifier.fillMaxSize(), topBar = { TopAppBar( title = { Text("My App") } ) }, floatingActionButton = { FloatingActionButton( onClick = { /* Handle click */ } ) { Icon( Icons.Filled.Add, contentDescription = "Add Button" ) } } ) { contentPadding -> val pagerState = rememberPagerState { 10 } HorizontalPager( state = pagerState, modifier = Modifier.padding(contentPadding) ) { /* Page contents */ } } }
Drawers
With Views, you implement a navigation drawer by using a
DrawerLayout as the root view. In turn, your CoordinatorLayout is a child view of the DrawerLayout. The DrawerLayout also contains another child view, such as a NavigationView, to display the navigation options in the drawer.In Compose, you can implement a navigation drawer using the
ModalNavigationDrawer composable. ModalNavigationDrawer offers a drawerContent slot for the drawer and a content slot for the screen's content.ModalNavigationDrawer( drawerContent = { ModalDrawerSheet { Text("Drawer title", modifier = Modifier.padding(16.dp)) HorizontalDivider() NavigationDrawerItem( label = { Text(text = "Drawer Item") }, selected = false, onClick = { /*TODO*/ } ) // ...other drawer items } } ) { Scaffold(Modifier.fillMaxSize()) { contentPadding -> // Scaffold content // ... } }
Snackbars
Scaffold provides a snackbarHost slot, which can accept a SnackbarHost composable to display a Snackbar.val scope = rememberCoroutineScope() val snackbarHostState = remember { SnackbarHostState() } Scaffold( snackbarHost = { SnackbarHost(hostState = snackbarHostState) }, floatingActionButton = { ExtendedFloatingActionButton( text = { Text("Show snackbar") }, icon = { Icon(Icons.Filled.Image, contentDescription = "") }, onClick = { scope.launch { snackbarHostState.showSnackbar("Snackbar") } } ) } ) { contentPadding -> // Screen content // ... }MigrationCommonScenariosSnippets.kt