在?给你的 compose 加上页面跳转吧

3,253 阅读2分钟

Andoird 传统的布局方式 xml 需要在使用的时候花费额外的时间解析创建 View,直接用 new View 对象又要写很多东西,为了性能直接自定义 View 画?那要敲的代码就更多了。试过 anko,也自己使用 Kotlin DSl 做过类似的布局方式,始终差点味。Flutter Sky 出现的时候似乎出现了曙光,但是新的语言,新的布局方式,而且和原有的项目兼容问题,想说爱你不容易;而且flutter 生成的so 超大文件,加上项目本身的 so 一直是 armv7,armv8a,x86,x86_64 四个平台都有支持 _(:з」∠)_

直到 Jetpack Compose 的出现,直接的基于 Kotlin 构建,不会额外的增加太多的包大小,加上 Flutter 语法的影响,compose 的东西接受起来就变得顺理成章起来。But,compose 从发布到现在这么久了,一直没有出现页面导航的组件,于是就有了这个

github.com/Modificator…

[TOC]

先看效果

集成

build.gradle 里面加入

dependencies {
    //...
    implementation 'com.patchself:compose-navigator:0.1.1'
    //...
}

如果用的是 gradle.kts, 在 build.gradle.kts 里面加入

dependencies {
    //...
    implementation("com.patchself:compose-navigator:0.1.1")
    //...
}

使用

在你承载 Compose 的 Activity 里加上

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //设置打开的第一个页面
        navigationController.initController(SplashPage())
        setContent {
            // 当然这里也可以先用主题包裹
            navigationController.viewContent()
        }
    }

    override fun onBackPressed() {
        // 页面跳转回退栈
        if (!navigationController.onBackPressed()){
            super.onBackPressed()
        }
    }
}

然后呢就可以写自己的页面了,继承 PageController,然后在里面写页面样式

class CustomPage : PageController() {
    override fun getId() = R.id.CustomPage

    /**
     * 在这个方法里写你的页面内容
     * @Composable 这个注解不会被继承需要自己加上去
     */
    @Composable
    override fun screenContent() {
        Scaffold(topBar = {
            TopAppBar(
                title = { Text(text = "Navigator Sample") },
                navigationIcon = {
                    IconButton(onClick = { navigateBack() }) {
                        Icon(asset = Icons.Filled.ArrowBack)
                    }
                },
                elevation = 4.dp
            )
        }) {
        }
    }
}

页面有关生命周期的方法

  • 当页面显示在前台显示会调用 onFocus
  • 当页面切到后台会调用 onBlur
  • 当页面被销毁会调用 destory

PageController 实现了 CoroutineScope 所以可以直接使用协程方法,在 destory 的时候会自动取消所有的协程,不用自己回收

跳转方式

打开新页面

最基础的打开新的页面,使用方式,在继承 PageController 的类里可以这样跳转到一个新的页面

navigateTo(NewPage().also{
    pageArgs = args
})

返回上一页

返回上一页也很简单,在页面内,直接调用 navigateBack() 就可以了

回退到特定页面(Clear Top)

回退到指定页面有两种调用方式,带参数和不带参数

resetTo(R.id.HomePage)
//如果需要修改回退目标的属性可以这么用
resetTo<HomePage>(R.id.HomePage){
       argsOfHomePage = newValue
}