Compose之跨平台Activity页面

14 篇文章 0 订阅
13 篇文章 0 订阅

前言

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视图都在这个函数内写
     */
    @Composable
    actual abstract fun ComposeContent()
}

android:

actual abstract class BaseComposeActivity : AppCompatActivity() {

    @Composable
    actual abstract fun ComposeContent()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyTheme {
                ComposeContent()
            }
        }
    }
}

desktop:

actual abstract class BaseComposeActivity {

    @Composable
    actual abstract fun ComposeContent()
}

这样我们一个基本的BaseComposeActivity就完成了,因为Android继承了AppCompatActivity类,所以可以直接通过Android的startActivity来启动,通过finish来销毁

而Desktop我们可以通过自定义一个页面栈,通过观察,添加,删除来管理页面:

将desktop的BaseComposeActivity改成这样:

actual abstract class BaseComposeActivity {

    @Composable
    actual 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一个Window
        Window(onCloseRequest = ::exitApplication) {
            MyTheme {
                //页面内容
                BaseComposeActivity._activityStack.forEachIndexed { index, baseActivity ->
                        //防止Compose生命周期变更导致的问题
                        key(baseActivity) {
                            Column(
                                //使栈顶的Activity有宽高,其他页面没有宽高,这样就可以有覆盖的效果了
                                if (index == 0)
                                    M.fillMaxSize()
                                        .background(Color.White)
                                else
                                    M.size(0.dp)
                            ) {
                                baseActivity.ComposeContent()
                            }
                        }
                }
            }
        }
    }
}

这样我们就封装好了一个跨平台的Activity

ps:后续出ios和web也可以类似如此的封装

我们可以直接在common中写Activity,比如:

class BannerActivity : BaseComposeActivity() {
    @Composable
    override 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)

如果大佬们有什么问题的话可以评论

对Kotlin或KMP感兴趣的同学可以进Q群 101786950

如果这篇文章对您有帮助的话

可以扫码请我喝瓶饮料或咖啡(如果对什么比较感兴趣可以在备注里写出来)

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值