MRouter,一款compose-multiplatform的路由库
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