Skip to main content

Use navigation

Required dependencies​

This page is standalone. The Android navigation artifact supplies the platform-neutral route model transitively.

build.gradle.kts
repositories { mavenCentral() }

dependencies {
implementation("com.viewcompose:viewcompose-material3-android:0.1.0-alpha02")
implementation("com.viewcompose:viewcompose-navigation-android:0.1.0-alpha02")
implementation("com.viewcompose:viewcompose-viewmodel-androidx:0.1.0-alpha02")
implementation("androidx.activity:activity:1.12.4")
implementation("com.google.android.material:material:1.13.0")
}

Create NavigationTutorialActivity.kt:

package com.viewcompose.samples.tutorials

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.lifecycle.ViewModel
import com.viewcompose.material3.android.setMaterial3UiContent
import com.viewcompose.navigation.NavHost
import com.viewcompose.navigation.rememberNavHostController
import com.viewcompose.navigation.core.NavRoute
import com.viewcompose.ui.modifier.Modifier
import com.viewcompose.ui.modifier.fillMaxSize
import com.viewcompose.ui.modifier.padding
import com.viewcompose.ui.unit.dp
import com.viewcompose.ui.foundation.Button
import com.viewcompose.ui.foundation.Column
import com.viewcompose.ui.foundation.Text
import com.viewcompose.ui.foundation.TextDefaults
import com.viewcompose.viewmodel.viewModel

private const val HOME = "home"
private const val DETAILS = "details"

class NavigationTutorialActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

setMaterial3UiContent {
val controller = rememberNavHostController(NavRoute(HOME))

NavHost(controller = controller) { entry ->
Column(
spacing = 12.dp,
modifier = Modifier.fillMaxSize().padding(24.dp),
) {
when (entry.route.name) {
HOME -> {
Text("Home", style = TextDefaults.titleLargeStyle())
Button(
"Open details",
onClick = { controller.navigate(NavRoute(DETAILS)) },
)
}
DETAILS -> {
val model = viewModel<DetailsViewModel>()
Text(model.title, style = TextDefaults.titleLargeStyle())
Button("Back", onClick = controller::popBackStack)
}
else -> error("Unknown route ${entry.route.name}")
}
}
}
}
}
}

class DetailsViewModel : ViewModel() {
val title: String = "Details"
}

The remembered controller owns the committed back stack. NavHost renders the current NavRoute and connects Android system Back to the same stack. Call navigate or popBackStack from UI events after the host is mounted.

This sample runs inside Activity setUiContent, which supplies the lifecycle and LocalViewModelStoreOwner required by NavHost. If the same content is mounted with low-level renderInto, provide those owner locals explicitly. Each destination then receives its own Lifecycle, saved-state namespace, and ViewModelStore leased from the retained parent store.

Verify the result​

Press Open details, then return with the on-screen Back action. Open Details again and use Android system Back. Both paths must return to Home exactly once. Compile with ./gradlew :samples:tutorials:assembleDebug.

For restoration, explicit failure handling, and predictive Back acceptance, continue with Configure a production navigation host.