Preview a "screen" in android jetpack compose navigation with a PreviewParameter NavController
Asked Answered
F

4

14

I am discovering android Jetpack Compose (and Navigation) and try to display a preview of a view with a navController as parameter.

To achieve this, I use the PreviewParameter and I have no error, but nothing is displayed in the Preview window.

Does anyone know how pass a fake NavController instance to a Composable?

class FakeNavController : PreviewParameterProvider<NavController> {
    override val values: Sequence<NavController>
        get() {}
}

@Preview
@Composable
fun Preview(
    @PreviewParameter(FakeNavController::class) fakeNavController: NavController
) {
    HomeView(fakeNavController)
}
Farmhand answered 28/11, 2021 at 18:39 Comment(0)
S
41

You don't have to make it nullable and pass null to it. You just need to pass this: rememberNavController()

@Preview
@Composable
fun Preview() {
    HomeView(rememberNavController())
}
Segalman answered 9/2, 2022 at 9:2 Comment(1)
Thanks! This is the solution. Should be marked as onePriceless
F
6

PreviewParameter is used to create multiple previews of the same view with different data. You're expected to return the needed values from values. In your example you return nothing that's why it doesn't work(it doesn't even build in my case).

That won't help you to mock the navigation controller, as you still need to create it somehow to return from values. I think it's impossible.

Instead you can pass a handler, in this case you don't need to mock it:

@Composable
fun HomeView(openOtherScreen: () -> Unit) {
    
}
// your Navigation view
composable(Destinations.Home) { from ->
    HomeView(
        openOtherScreen = {
            navController.navigate(Destinations.Other)
        },
    )
}
Frodin answered 29/11, 2021 at 0:7 Comment(1)
Thanks for your help. My problem is to display a preview of a screen which take as parameter a NavController. Because my screen is in another file, I don't know how to deal with it. But your answer help me to understand the purpose of PreviewParameter. best regardFarmhand
C
0

That happens due to the limitations of jetpack compose when dealing with external libraries, but there is a solution that I tried: 1-Don't pass navController to the screen, instead pass a funtion type( onMoveButtonClick:()->Unit ) for the screen that you have. 2-In the navGraph you specify what should happen when clicking the button like this:

HomeView(

    onMoveButtonClick={
         navController.navigate(...)
}

)

in the preview pass empty lambda like this

    @Preview
    @Composable
    fun Preview(){
        HomeView(onMoveButtonClick={})
    }

for more help send me here: [email protected]

Chimere answered 17/5, 2024 at 8:16 Comment(0)
F
-1

Finally, I declare a nullable NavController and it works.

@Composable
fun HomeView(navController: NavController?) {
    Surface {
        Column(
            modifier = Modifier
                .padding(all = 4.dp)
        ) {
            Text(
                text = "Home View",
                style = MaterialTheme.typography.body2
            )

            Spacer(modifier = Modifier.height(8.dp))

            Button(onClick = { navController?.navigate("lineRoute") }) {
                Text(text = "nav to Line view")
            }
        }
    }
}


@Preview
@Composable
fun Preview (){
    HomeView(null)
}
Farmhand answered 29/11, 2021 at 7:49 Comment(2)
Hi, There's a way to inject mock nav controller to test the navigation in preview?Basque
This doesn't work and doesn't even makes sense specially since we are suppose to use the preview parameter to display different states of the viewDeflected

© 2022 - 2025 — McMap. All rights reserved.