Dynamic Navigation in Android
Use Navigation 3 to set up a catch-all navigation strategy in your Android project and render new stories dynamically.
Add dependencies
Section titled “Add dependencies”In the version catalog TOML file, add the Navigation 3 libraries.
[versions]agp = "9.2.1"…storyblok = "0.3.0"nav3Core = "1.0.1"
[libraries]androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }…storyblok-material3-android = { group = "com.storyblok", name = "storyblok-material3-android", version.ref = "storyblok" }androidx-navigation3-runtime = { module = "androidx.navigation3:navigation3-runtime", version.ref = "nav3Core" }androidx-navigation3-ui = { module = "androidx.navigation3:navigation3-ui", version.ref = "nav3Core" }
[plugins]android-application = { id = "com.android.application", version.ref = "agp" }…Update app/build.gradle.kts to add the dependencies.
…dependencies { implementation(platform(libs.androidx.compose.bom)) … implementation(libs.storyblok.material3.android) implementation(libs.androidx.navigation3.ui) implementation(libs.androidx.navigation3.runtime)}Now select Sync Project with Gradle Files to download the added dependencies and re-analyze the project.
Create a story navigation key
Section titled “Create a story navigation key”Create a StoryKey.kt file to define a navigation key that can represent any story, identified by either its UUID or slug.
package com.example.myapplication
import androidx.navigation3.runtime.NavKeyimport com.storyblok.cdn.schema.Componentimport com.storyblok.cdn.schema.Storyimport kotlinx.serialization.EncodeDefaultimport kotlinx.serialization.Serializableimport kotlinx.serialization.Transientimport kotlin.uuid.Uuid
@Serializabledata class StoryKey( @Transient val story: Story<out Component>? = null, @EncodeDefault val uuid: Uuid? = story?.uuid, @EncodeDefault val slug: String? = story?.slug,) : NavKey
val HomeKey = StoryKey(slug = "home")StoryKey is a NavKey that persists the uuid or slug of a story to the back stack. It can also be constructed with a Story instance for immediate display when navigating between screens.
Display the back stack
Section titled “Display the back stack”In your MainActivity.kt file, add the code to initialize and use a NavDisplay to render the top of the back stack.
…import kotlinx.coroutines.flow.onCompletionimport androidx.navigation3.runtime.rememberNavBackStackimport androidx.navigation3.ui.NavDisplayimport androidx.navigation3.runtime.entryProvider
class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { MyApplicationTheme { Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
val backStack = rememberNavBackStack(HomeKey)
Storyblok( accessToken = "YOUR_ACCESS_TOKEN", version = if (BuildConfig.DEBUG) Draft else Published, region = EU, // Choose the correct region from your Space. … ) { NavDisplay( backStack, Modifier.padding(innerPadding), entryProvider = entryProvider { entry<StoryKey> { key ->
var isRefreshing: Boolean by remember { mutableStateOf(true) }
val story by remember { snapshotFlow { isRefreshing } .filter { it } .flatMapLatest { story("home").onCompletion { isRefreshing = false } val story = when(key.uuid) { null -> story(slug = key.slug!!) else -> story(uuid = key.uuid) } story.onCompletion { isRefreshing = false } } } .collectAsStateWithLifecycle(null) .collectAsStateWithLifecycle(key.story)
PullToRefreshBox( isRefreshing = isRefreshing, onRefresh = { isRefreshing = true }, modifier = Modifier.fillMaxSize() ) { story?.content?.let { Block(it, Modifier.padding(innerPadding)) } story?.content?.let { Block(it) } } } } ) } } } } }}…The single entry<StoryKey> handles every possible story destination. It fetches the story by UUID or slug, populating the initial value of collectAsStateWithLifecycle with the key’s story instance so available content appears immediately.
With this approach, the project automatically handles new stories that are added to the space and pushed onto the back stack.
Related resources
Section titled “Related resources”Was this page helpful?
This site uses reCAPTCHA and Google's Privacy Policy (opens in a new window).Terms of Service (opens in a new window) apply.
Get in touch with the Storyblok community