likes
comments
collection
share

MRouter,一款compose-multiplatform的路由库

作者站长头像
站长
· 阅读数 61

compose-multiplatform是使用kotlin实现的跨平台声明式UI框架,截止目前(2024年6月8日)compose for ios 已进入了beta阶段,compose for wasmJs 已进入了alpha阶段,恭喜🎉🎉。

简介

MRouter是适用于compose-multiplatform的路由库,其实现了路由跳转,参数传递,页面变换,手势,共享元素,局部路由等功能,MRouter也对lifecycle和viewmodel进行了适配。

MRouter目前仅适配了android,ios,desktop(JVM)以及wasmJS平台,对于其他的平台后续会逐渐补上。

安装

在项目的build.gradle.kts中加入依赖:

commonMain.dependencies {
    implementation("cn.erolc.mrouter:core:<version>")
}

version可前往MRouter查看

起点

路由的起点是RouteHost函数,在common中使用:

@Composable
fun App() {
    MaterialTheme {
        RouteHost("home") {
            page("home") {
                Home()
            }
            page("second") {
                Second()
            }
        }
    }
}

如此便将两个composable函数注册成了页面,并以home作为起始页面。

注册

在路由之前,需要先将页面注册到库中,这样路由的时候才能访问的到。 地址的格式一般是url的path,也就是A/B/C,支持动态路径,比如:A/B/{xxx},以{xxx}作为占位符。。注册除了page方法之外还有module方法。

page("A/B/C"){

}
module("A"){
    page("B/C"){

    }
}

以上两个地址是同一个,如果在注册时地址重复了,那么后者将会覆盖前者。

除此之外,还支持使用platformRoute方法注册平台界面,比如Activity,UIViewController,可直接通过地址路由到对应的平台界面。

路由

注册完界面之后就可以开始路由了,所有页面都会有一个PageScope的类,作为描述页面的作用域,可使用LocalPageScope获得。

val pageScope = LocalPageScope.current
//code...
pageScope.route("A/B/C?key=xxx"){ //支持query参数传递
    argBuild{//也可以使用参数构造工具设置构造的参数
        putString("key1","xxxx")
    }
    transform = normal() // 支持使用封装好的变换
    Transform{ //也支持这种方式
        enter = slideInHorizontally { it } // 支持只设置enter,那么在exit时将也会使用enter不过效果是相反的。
    }
    window("id") // desktop支持多窗口模式,其他平台暂不支持
    panel("local") //支持将该页面加载到当前界面对应key的panel上,等价于:local:A/B/C
    onResult{
        //在这里获取页面返回时传递过来的值。
    }
}

val arg = rememberArg() //获取从前一个页面传递过来的值。

pageScope.setResult(bundleOf()) //  设置返回时需要传递的值
pageScope.onBackPressed() // 后退

以上便是pageScope的大致功能方法,也将是最常用的方法。

页面变换

在路由时设置transform便可实现路由过程中页面的变换,包括当前界面也包括上一个界面。目前预设的有: normal:右进右出,且页面左边有15dp的手势区域 modal:类ios的modal样式,即使用presentViewController方法打开的效果。 none:无手势的normal share:共享控件时使用

页面变换所用到的slideInHorizontally等方法都是MRouter库实现的,但使用方式和效果与原生无异。

局部路由

可以在界面内使用PanelHost设置一个页面的局部路由,当在外部通过key:path的方式进行导航时,就会导航到当前界面key的panel上,且panel可感知窗口大小,可设置当窗口大小发生变化时显示或隐藏。

@Composable
fun Page1(){
    
    Row{
        //code...
        PanelHost(key="xxx",startRoute="xxxx")
    }
}

panel存在默认的key(local)和默认的startRoute(default)你可以通过注册default覆盖这个默认页面。

panel外部需要key才能路由到panel内部,而在panel内部路由则无需key。目前尚不支持从panel内部路由到panel外部

共享元素

当你需要使用共享元素时,只需在两个页面中使用Element函数,两者使用相同的key,这就是共享的元素,然后在route时设置transform=share("key")即可。

//page1
Button(onClick={
    pageScope.route("page2"){
        transform = share("ele_key")
    }
})

Element("ele_key"){
    //code...
}

//page2
Element("ele_key"){
    //code...
}

共享元素内部变换

上述是简单的共享元素使用,当你需要共享元素内部的样式也需要在共享过程中进行变换,比如希望共享元素的背景颜色可以顺滑的过渡,那么需要进阶一下。

//page1
Button(onClick={
    pageScope.route("page2"){
        transform = share("ele_key")
    }
})

Element("ele_key",styles=listOf(Color.Red)){
    val bgColor by getStyle(0, animate = animateColor())
    //code...
}

//page2
Element("ele_key",styles=listOf(Color.Blue)){
    val bgColor by getStyle(0, animate = animateColor())
    //code...
}

这样共享元素内部直接使用bgColor即可。除了color,还支持Int,Offset等多种值,如果有特殊的值,可使用animateValue方法进行自定义。 当需要共享元素内部变换响应手势,只需要给getStyle方法设置sharing即可:

    val bgColor by getStyle(0,sharing = ::sharing, animate = animateColor())

如此,bgColor的值将会随着手势的进度而变化。

Lifecycle&ViewModel

MRouter适配了官方的Lifecycle和ViewModel,使用Lifecycle管理Page的生命周期。在page中使用LifecycleObserver函数即可:

LifecycleObserver { _, event ->
    loge("tag", "$event")
}

当你需要使用ViewModel时,可直接在Composable函数中通过viewModel方法构建:

val viewModel = viewModel(::FirstViewModel)

该方法仅支持无参构造函数和SavedStateHandle参数的ViewModel,如果有更复杂的ViewModel构造需求,建议使用依赖注入框架,比如koin

总结

MRouter是一个可以用于compose-multiplatform和jetpack compose的路由库,能很方便的实现页面变换,共享元素等多种功能,欢迎前往github了解并使用该库:MRouter。有任何问题,建议,欢迎私信,评论或提issues。如果对你有帮助,希望可以点个star,感谢🙏。

转载自:https://juejin.cn/post/7377741132823953444
评论
请登录