Jetpack Compose 多界面间的路由跳转

文章目录

    目录结构

    一个简单 Demo 的文件分离结构:

    • Home Screen:首页列表
    • Edit Screen (detail):编辑页
    • NavHost (router):路由定义
    • Main Activity

    添加依赖

    dependencies {
        implementation "androidx.navigation:navigation-compose:2.4.0-alpha08"
    }
    

    添加之后,不要忘了点击 Android Studio 右上角的 Sync Now。
    否则像 rememberNavController 这样的函数,无法通过 Alt + Enter 自动添加引用。

    注意:同时需要将 build.gradle 中的 compileSdk 和 targetSdk 由 30 修改为 31,否则会报错。
    详见下面的编译错误记录。

    这个版本号,应该是随时在更新的。如何查看最新的版本号?

    navigation-compose 引起的编译报错

    在 preview 预览编译时,报错:

    FAILURE: Build failed with an exception.
    
    * What went wrong:
    Execution failed for task ':app:checkDebugAarMetadata'.
    > A failure occurred while executing com.android.build.gradle.internal.tasks.CheckAarMetadataWorkAction
       > One or more issues found when checking AAR metadata values:
         
         The minCompileSdk (31) specified in a
         dependency's AAR metadata (META-INF/com/android/build/gradle/aar-metadata.properties)
         is greater than this module's compileSdkVersion (android-30).
         Dependency: androidx.navigation:navigation-compose:2.4.0-alpha08.
    

    从提示上看是,androidx.navigation:navigation-compose:2.4.0-alpha08 依赖 minCompileSdk 31,
    而 build.gradle 中设置的 compileSdk 为 30.

    解决方法就是将 compileSdk 和 targetSdk 都由 30 改为 31.

    android {
        compileSdk 31
    
        defaultConfig {
            applicationId "com.sunzhongwei.app"
            minSdk 21
            targetSdk 31
    

    再次编译成功。

    NavHost

    定义路由:

    enum class DemoScreen {
        HomeScreen,
        EditScreen
    }
    
    @Composable
    fun DemoNavHost(
        navController: NavHostController
    ) {
        NavHost(
            navController = navController,
            startDestination = DemoScreen.HomeScreen.name
        ) {
            composable(DemoScreen.HomeScreen.name) {
                HomeScreen(navController = navController)
            }
            composable(DemoScreen.EditScreen.name) {
                EditScreen(navController = navController)
            }
        }
    }
    
    • NavController: 记录 path 栈
    • NavHost: 定义多 composable 界面间的路由关系

    HomeScreen

    定义首页界面 UI, 及操作

    @Composable
    fun HomeScreen(navController: NavController) {
        Scaffold(
            drawerContent = { /*...*/ },
            topBar = { /*...*/ },
            content = {
                Items(items)
            },
            floatingActionButton = {
                FloatingActionButton(onClick = {
                    navController.navigate(ShelfLifeScreen.EditScreen.name)
                }) {
                    Icon(Icons.Filled.Add,"")
                }
            } 
        )
    }
    

    EditScreen

    @Composable
    fun EditScreen(navController: NavController) {
        Text(text = "test")
    }
    

    MainActivity

    class MainActivity : ComponentActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContent {
                ComposeNavigation()
            }
        }
    }
    
    @Composable
    fun ComposeNavigation() {
        val navController = rememberNavController()
    
        DemoNavHost(
            navController = navController,
        ) 
    }
    

    带有 NavController 的 composable 如何预览

    由于 HomeScreen 添加了 NavController 参数,所以预览失效:

    No value passed for parameter ‘navController’

    加上一个参数即可。

    @Preview
    @Composable
    fun PreviewHome() {
        val navController = rememberNavController()
        HomeScreen(navController)
    }
    

    参考

    关于作者 🌱

    我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊,或者关注我的个人公众号“大象工具”, 查看更多联系方式