前言
Compose(Jetpack+jb)是可以跨平台的
目前跨平台主流的页面导航方式一般有两种
一种是都在同一个页面内进行页面替换类型的导航,类似于单Activity,多Fragment
另一种是不同的页面在不同的页面载体上,类似多Activity
两种页面导航方式都可以使用,但我比较偏向于使用多Activity的方案(见仁见智)
分析
拿Compose跨Android和Desktop来举例
Android的载体有Activity,Fragment,Compose fun
Desktop的载体有Window,Compose fun
我们可以使用Kotlin expect来关联Android的Activity和Desktop的Compose fun(或Window),写一个统一的类BaseComposeActivity
这样BaseComposeActivity在Android中就映射为一个真正的Activity,而在Desktop中映射为一个Compose fun,方便我们进行页面导航
正文
我们先写一个最简单的BaseComposeActivity出来,然后后面有需求我们在加东西
common:
/*** creator: lt 2021/4/27 lt.dygzs@qq.com* effect : 以Compose为根View的ba* warning:*/
expect abstract class BaseComposeActivity() {/*** compose根布局,我们页面的Compose视图都在这个函数内写*/@Composableactual abstract fun ComposeContent()
}
android:
actual abstract class BaseComposeActivity : AppCompatActivity() {@Composableactual abstract fun ComposeContent()override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {MyTheme {ComposeContent()}}}
}
desktop:
actual abstract class BaseComposeActivity {@Composableactual abstract fun ComposeContent()
}
这样我们一个基本的BaseComposeActivity就完成了,因为Android继承了AppCompatActivity类,所以可以直接通过Android的startActivity来启动,通过finish来销毁
而Desktop我们可以通过自定义一个页面栈,通过观察,添加,删除来管理页面:
将desktop的BaseComposeActivity改成这样:
actual abstract class BaseComposeActivity {@Composableactual abstract fun ComposeContent()actual fun mFinish() {//移除页面(可以改为remove(this))_activityStack.removeLast()}actual fun jump(clazz: Class<out BaseComposeActivity>) {//跳转页面,往栈中加入新页面//ps:这里可以做各种传参,生命周期或启动模式等的处理,此篇就不在赘述_activityStack.add(clazz.newInstance())}companion object {//自定义的任务栈,可以被Compose所观察val _activityStack = mutableStateListOf<BaseComposeActivity>(MainActivity())}
}
最后给Desktop的Application(main函数)添加BaseComposeActivity支持
fun main(vararg args: String) {//desktop的根应用application {//将所有页面放在一个Window中,也可以稍加修改改为每个BaseComposeActivity一个WindowWindow(onCloseRequest = ::exitApplication) {MyTheme {//页面内容BaseComposeActivity._activityStack.forEachIndexed { index, baseActivity ->//防止Compose生命周期变更导致的问题key(baseActivity) {Column(//使栈顶的Activity有宽高,其他页面没有宽高,这样就可以有覆盖的效果了if (index == 0)M.fillMaxSize().background(Color.White)elseM.size(0.dp)) {baseActivity.ComposeContent()}}}}}}
}
这样我们就封装好了一个跨平台的Activity
ps:后续出ios和web也可以类似如此的封装
我们可以直接在common中写Activity,比如:
class BannerActivity : BaseComposeActivity() {@Composableoverride fun ComposeContent() {val bannerState = rememberBannerState()Banner(colors.size,M.fillMaxSize(),bannerState = bannerState,autoScrollTime = 1000,orientation = Orientation.Vertical,) {}//jump<BannerActivity>()//finish()}}
desktop上的效果如下所示(Android和之前一样就不演示了):
结语
当然跨平台的导航也可以使用单个页面内导航,可能对于Compose来说会更简单一点,但可能会少了一些灵活性
其实内部也可以将跨平台的toast和dialog封装到Activity中,如果你看懂了这篇文章,那对你来说应该也是很简单,下面的链接有示例
ps:完整代码可以参考(欢迎各位大佬star):ComposeViews(github)
如果大佬们有什么问题的话可以评论