Skip to content

导航Compose

Season edited this page Dec 8, 2023 · 1 revision

Compose导航基本用法

在需要导航的Composable组件上添加@Destination注解,并设置对应的route路径,然后调用navigate方法并传入目的地的路径即可。

//定义目的地
@Destination(Destinations.COMPOSE)
@Composable
fun ComposeScreenTest() {
    
}

//导航
Butterfly.of(context).navigate(Destinations.COMPOSE)

route路径可以是任意字符串常量,通常我们使用scheme://path/xxx这样的格式作为route地址

Compose参数传递和解析

Compose导航支持多种参数传递方式,可通过拼接路径的形式带入额外的参数,或者通过调用params方法手动传入参数, 或者在调用navigate方法时传入参数,或者混合使用以上几种方式。

//拼接路径带入参数
Butterfly.of(this).navigate(Destinations.COMPOSE + "?a=1&b=2&c=3")

//调用params方法
Butterfly.of(this)
    .params(
        "x" to 1,
        "y" to true,
        "z" to "test value"
    )
    .navigate(Destinations.COMPOSE)

//调用navigate时传入参数
Butterfly.of(this)
    .navigate(
        Destinations.COMPOSE,
        "a" to "1"
    )

//同时使用多种方式
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"
    )

以上几种方式的优先级为:navigate > route string > params,也就是说如果遇到同名的参数, 则通过navigate方法传递的参数会覆盖拼接路径字符串中的参数,拼接路径字符串中的参数又会覆盖通过params方法传递的参数。

传入的参数会打包成一个Bundle对象,如果Compose组件需要获取参数,需要添加Bundle类型的参数进行获取。

@Destination(Destinations.COMPOSE)
@Composable
fun ComposeScreenTest(bundle: Bundle) { 
    //添加Bundle类型参数,导航的参数便可通过该参数获取
    val a by bundle.params<String>()
    val b by bundle.params<String>()
    val c by bundle.params<String>()
}

Compose启动模式设置

Butterfly同样支持设置Compose的启动模式,默认情况下使用standard模式启动, 通过调用singleTopclearTop方法,可以设置为栈顶复用模式或者清除栈顶模式启动。

// 设置为 clearTop 模式,如果当前栈中有目标类型的Compose,则会清除目标上面的所有Compose,
// 确保目标Compose位于栈顶位置,否则创建新的Compose入栈
Butterfly.of(context)
    .clearTop()
    .navigate(Destinations.Compose)

// 设置为 singleTop 模式,如果栈顶已经是该目标Compose,则保持目标Compose不变,
// 否则创建新的Compose入栈
Butterfly.of(context)
    .singleTop()
    .navigate(Destinations.Compose)

在这两种启动模式下,如果复用了栈中的目标Compose,新的导航参数会重新传递给Compose,从而触发页面重组刷新。

Compose容器设置

Compose导航默认使用ContentView作为容器,可以通过container方法设置为自定义的ViewGroup容器。

Butterfly.of(context)
    .container(R.id.container)  //指定容器的ID
    .container("container_tag") //或者指定容器的Tag
    .navigate(Destinations.Compose)

Compose回退及返回结果

使用Butterfly进行导航Compose之后,如需返回可以使用popBack方法进行回退。

如果Compose回退的时候需要携带返回值,使用popBack可以直接传入返回值。

@Destination(Destinations.COMPOSE)
@Composable
fun ComposeScreenTest(bundle: Bundle = bundleOf()) {
    val ctx = LocalContext.current
    Surface(modifier = Modifier.fillMaxSize()) {
        Button(onClick = {
            //回退
            Butterfly.of(ctx).popBack()
            
            //回退并返回结果
            Butterfly.of(ctx).popBack("result" to "123")
        }) {
            Text(text = "Back")
        }
    }
}

返回结果会被封装为一个Bundle对象,通过解析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)
    }
}

Compose组管理

Butterfly除了支持以栈的形式来管理Compose,还支持以Group组的形式对Compose进行管理,常用于主页或Tab页面。

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