david CHOLLEZ
david CHOLLEZ

Reputation: 167

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

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)
}

Upvotes: 16

Views: 11213

Answers (4)

Ali Shafeek Ahmad
Ali Shafeek Ahmad

Reputation: 31

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]

Upvotes: 0

Alireza Nezami
Alireza Nezami

Reputation: 715

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())
}

Upvotes: 46

david CHOLLEZ
david CHOLLEZ

Reputation: 167

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)
}

Upvotes: -1

Phil Dukhov
Phil Dukhov

Reputation: 88132

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)
        },
    )
}

Upvotes: 6

Related Questions