Skip to content

Navigate_Compose

Season edited this page Dec 8, 2023 · 1 revision

Basic Usage

Add @Destination annotation to the Composable component to be navigated, set the corresponding route path, and then call the navigate method and pass in the path of the destination.

//Define destination
@Destination(Destinations.COMPOSE)
@Composable
fun ComposeScreenTest() {
    
}

//Navigation
Butterfly.of(context).navigate(Destinations.COMPOSE)

The route path can be any string constant, and usually we use a format such as scheme://path/xxx as the route address

Parameter Transfer And Parsing

Compose navigation supports a variety of parameter transfer methods. Additional parameters can be passed in the form of concatenation paths, or parameters can be manually passed in by calling the params method. Either pass in parameters when calling the navigate method, or use a mixture of the above.

//Stitching path input parameters
Butterfly.of(this).navigate(Destinations.COMPOSE + "?a=1&b=2&c=3")

//Call the params method
Butterfly.of(this)
    .params(
        "x" to 1,
        "y" to true,
        "z" to "test value"
    )
    .navigate(Destinations.COMPOSE)

//Pass parameters when calling navigate
Butterfly.of(this)
    .navigate(
        Destinations.COMPOSE,
        "a" to "1"
    )

//Use multiple ways at the same time
Butterfly.of(this)
    .params(
        "x" to 1,
        "y" to true,
        "z" to "test value"
    )
    .navigate(
        Destinations.COMPOSE + "?a=1&b=2&c=3",
        "d" to "4"
    )

The priority of the above methods is: navigate > route string > params, that is, if you encounter parameters with the same name, parameters passed through the navigate method override parameters in the splice path string, which in turn override parameters passed through the params method.

The passed parameters are packaged into a Bundle object. If the Compose component needs to obtain parameters, you need to add parameters of type Bundle to obtain them.

@Destination(Destinations.COMPOSE)
@Composable
fun ComposeScreenTest(bundle: Bundle) { 
    //Add a Bundle type parameter, and the navigation parameters can be obtained from this parameter
    val a by bundle.params<String>()
    val b by bundle.params<String>()
    val c by bundle.params<String>()
}

Launch Mode Settings

Butterfly also supports setting the startup mode of Compose, which is launched in standard mode by default. By calling the singleTop and clearTop methods, you can set the mode to reuse on the top of the stack or clear the top of the stack to start.

// Set to clearTop mode. If there is a Compose of the target type in the current stack, all Compose above the target will be cleared.
// Make sure the target Compose is at the top of the stack, otherwise create a new Compose and push into stack
Butterfly.of(context)
    .clearTop()
    .navigate(Destinations.Compose)

// Set to singleTop mode. If the target Compose is already at the top of the stack, keep the target Compose unchanged.
// Otherwise, create a new Compose and push into stack
Butterfly.of(context)
    .singleTop()
    .navigate(Destinations.Compose)

In both startup modes, if the target Compose in the stack is reused, the new navigation parameters are passed back to Compose, triggering the page reorganization refresh.

Container Settings

Compose navigation uses ContentView as a container by default, and can be set to a custom ViewGroup container by container method.

Butterfly.of(context)
    .container(R.id.container)  //Specify the ID of the container
    .container("container_tag") //Or specify the Tag of the container
    .navigate(Destinations.Compose)

Returns And Returns Results

After using Butterfly to navigate Compose, if you need to return, you can use the popBack method to fallback.

If you need to bring the return value with Compose when fallback, you can pass the return value directly using popBack.

@Destination(Destinations.COMPOSE)
@Composable
fun ComposeScreenTest(bundle: Bundle = bundleOf()) {
    val ctx = LocalContext.current
    Surface(modifier = Modifier.fillMaxSize()) {
        Button(onClick = {
            //pop back
            Butterfly.of(ctx).popBack()
            
            //pop back and return data
            Butterfly.of(ctx).popBack("result" to "123")
        }) {
            Text(text = "Back")
        }
    }
}

The returned result will be encapsulated as a Bundle object, and the returned result can be obtained by parsing Bundle:

Butterfly.of(context).navigate(Destinations.Compose) { result ->
    if (result.isSuccess) {
        val bundle = result.getOrDefault(Bundle.EMPTY)
        val result by bundle.params<String>()
        println(result)
    }
}

Group Management

Butterfly not only supports the management of Compose in the form of stacks, but also supports the management of Compose in the form of Group groups, which is often used in home pages or Tab pages.

@Destination(Destinations.Test)
class BottomNavigationActivity : AppCompatActivity() {

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

        val groupId = "test_group"
        binding.navView.setOnItemSelectedListener {
            when (it.itemId) {
                R.id.navigation_home -> {
                    Butterfly.of(this)
                        .container(R.id.container)
                        .group(groupId)
                        .navigate(Destinations.COMPOSE_HOME)
                }

                R.id.navigation_dashboard -> {
                    Butterfly.of(this)
                        .container(R.id.container)
                        .group(groupId)
                        .navigate(Destinations.COMPOSE_DASHBOARD)
                }

                R.id.navigation_notifications -> {
                    Butterfly.of(this)
                        .container(R.id.container)
                        .group(groupId)
                        .navigate(Destinations.COMPOSE_NOTIFICATION)
                }
            }
        }
    }
}