Quick Start Guide
Here's the improved version of your documentation text:
From this tutorial, you will learn how to start using Modo. You will learn how to:
Create a
Screenand integrate it into an activityPerform basic navigation operations
Pass arguments to screens
Customize
StackScreenanimation and content
At the end of this tutorial, you will have a simple application with a single screen and basic navigation.

Before You Start
Make sure that:
You have Android Studio and the Android SDK installed
You know the basics of Android development, such as creating activities and fragments, and can launch an application.
Build Your First Modo Application with a Single Screen
Setup Dependencies
In your module-level build.gradle(.kts) file, add the Modo Compose dependency:
Create Your First Screen
To display UI using Modo, you need to create a Screen implementation. Let's create a simple QuickStartScreen and implement it step-by-step:
Create a new Kotlin file
QuickStartScreen.kt:// TODO: provide Parcelable implementation class QuickStartScreen( // TODO: implement screenKey ) : Screen { @Composable override fun Content(modifier: Modifier) { // TODO: implement your UI } }Override the
Contentfunction to provide the UI for your screen. Don't forget to usemodifierin your root element:@Composable override fun Content(modifier: Modifier) { Box(modifier = modifier) { Text( text = "Hello, Modo!", modifier = Modifier.align(Alignment.Center) ) } }Implement the
Parcelableinterface for yourScreen. It's needed to support saving and restoring the screen's structure. You can easily do it by using the parcelable gradle plugin and the@Parcelizeannotation:@Parcelize class QuickStartScreen( ... ) : Screen { ... }Implement the
screenKeyproperty using thegenerateScreenKey()function. It's crucial to use this function because it generates a unique key for each screen:@Parcelize class QuickStartScreen( // You need to generate a unique screen key using a special function override val screenKey: ScreenKey = generateScreenKey() ) : Screen { ... }
Complete code:
Integrate the Screen into the Activity
Now that we've created QuickStartScreen, let's integrate it into an activity.
Create a new activity
QuickStartActivityand add the following code:class QuickStartActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { // TODO: integrate screen } } }Integrate the
QuickStartScreeninto the activity. To do so, use therememberRootScreenfunction to create a root screen that will manage navigation:setContent { val rootScreen = rememberRootScreen { QuickStartScreen() } // TODO: display the root screen }Display the root screen using the
Contentfunction of the root screen:setContent { val rootScreen = rememberRootScreen { QuickStartScreen() } // Pass fillMaxSize modifier to display it in full screen rootScreen.Content(Modifier.fillMaxSize()) }
Complete code:
Run the Application!

Perform Basic Navigation Operations
To perform navigation, let's use a StackScreen. It's a container screen that can contain multiple child screens and renders the top one.
Use the
DefaultStackScreenin your activity:setContent { val rootScreen = rememberRootScreen { DefaultStackScreen( // Use StackNavModel to define the initial screen StackNavModel( QuickStartScreen() ) ) } rootScreen.Content(modifier = Modifier.fillMaxSize()) }Let's create
QuickStartScreenContent, with a title and a button that will navigate to another screen:@Composable private fun QuickStartScreenContent( modifier: Modifier, openNextScreen: () -> Unit, ) { Column( modifier = modifier, verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { Text(text = "Hello, Modo!") Button( onClick = openNextScreen ) { Text(text = "Next screen") } } }To navigate to the next screen, we need to retrieve the
StackNavContainer. You can get the nearestStackNavContainerfrom theContentfunction using theLocalStackNavigationcomposition local. In our case, it's going to beDefaultStackScreenthat we defined earlier:@Composable override fun Content(modifier: Modifier) { val stackNavigation = LocalStackNavigation.current QuickStartScreenContent( modifier = modifier, openNextScreen = { // TODO: navigate using stackNavigation }, ) }To navigate to the next screen, use the
forwardfunction of theStackNavContainerand pass a new screen to it:QuickStartScreenContent( modifier = modifier, openNextScreen = { stackNavigation.forward(QuickStartScreen()) }, )Launch the application and check the result! Try to navigate to the next screen by clicking the button and navigate back using the back button.
Complete code:
Pass Arguments to Screens
To pass arguments to the screen, you can use the constructor argument.
Let's add a screen index to the
QuickStartScreen:@Parcelize class QuickStartScreen( private val screenIndex: Int, override val screenKey: ScreenKey = generateScreenKey() ) : Screen { ... }Use the
screenIndexargument in theContentfunction to display it:@Composable override fun Content(modifier: Modifier) { val stackNavigation = LocalStackNavigation.current QuickStartScreenContent( modifier = modifier, screenIndex = screenIndex, openNextScreen = { stackNavigation.forward(QuickStartScreen(screenIndex + 1)) }, ) }Use the
screenIndexin theQuickStartScreenContent:@Composable private fun QuickStartScreenContent( modifier: Modifier, screenIndex: Int, openNextScreen: () -> Unit, ) { Column( modifier = modifier, verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { Text(text = "Hello, Modo! Screen №$screenIndex") Button( onClick = openNextScreen ) { Text(text = "Next screen") } } }
Customize StackScreen Animation and Content
Before, we used the built-in DefaultStackScreen that implements StackScreen and provides default animation and content. Let's take DefaultStackScreen as a starting point and customize it.
Create a Custom StackScreen
Copy the DefaultStackScreen implementation and change its name to QuickStartStackScreen:
Everything is quite similar to declaring a Screen. Let's look at the differences:
private val navModel: StackNavModelin the constructor is used to store and update the state of the navigation. Declaring it as a constructor parameter allows it to be saved and restored using the@Parcelizeannotation. Don't forget to pass it to theStackScreen's constructor.TopScreenContent(modifier)is used to render the last screen in the stack.ScreenTransition(modifier)insideTopScreenContentis used to animate the transition between screens.
Custom Animation
Let's customize the animation a little bit. You can do it by passing
transitionSpecas aScreenTransitionparameter:ScreenTransition( modifier = modifier, transitionSpec = {Inside the
transitionSpeclambda, we have access to theComposeRendererScopethat contains the old and new states. Let's use the built-incalculateStackTransitionTypeto determine the StackTransitionType:transitionSpec = { val screenTransitionType = calculateStackTransitionType()Now we can use
StackTransitionTypeto define the animation. Let's useslideInHorizontallyandslideOutHorizontallywith different parameters for the forward and back transitions:val screenTransitionType = calculateStackTransitionType() when (screenTransitionType) { StackTransitionType.Push -> { slideInHorizontally(initialOffsetX = { it }) togetherWith slideOutHorizontally(targetOffsetX = { -it }) } StackTransitionType.Pop -> { slideInHorizontally(initialOffsetX = { -it }) togetherWith slideOutHorizontally(targetOffsetX = { it }) } StackTransitionType.Replace, StackTransitionType.Idle -> fadeIn() togetherWith fadeOut() } }
Customize QuickStartStackScreen Content
You can customize Content as a regular composable function. Let's modify QuickStartStackScreen. Draw the background and make screens render with rounded corners:
You can pass a modifier to the
TopScreenContentfunction to change it:TopScreenContent( Modifier .background(Color.Cyan) .padding(16.dp) .clip(shape = RoundedCornerShape(32.dp)) .fillMaxSize() .background(Color.White) ) { screenModifier -> }You can also put the
TopScreenContentinside another container to customize it. Let's put it inside aBoxand add buttons to close the activity:Box(modifier = modifier) { TopScreenContent( ) { screenModifier -> } val context = LocalContext.current IconButton( modifier = Modifier .align(Alignment.TopEnd) .padding(8.dp) .clip(CircleShape) .background(Color.White), onClick = { context.getActivity()?.finish() } ) { Icon( painter = rememberVectorPainter(image = Icons.Default.Close), contentDescription = "Close quick start activity" ) } }
Complete code:
What You've Learned
From this tutorial, you've learned how to build a simple application with Modo and customize it for your needs. For further learning, you can explore the Sample app.