当前位置: 首页 > news >正文

【Compose multiplatform教程24】导航与路由

导航库目前处于实验阶段。

导航是用户界面(UI)应用程序的关键部分,它能让用户在应用程序的不同屏幕之间进行切换。Compose 多平台采用了 Jetpack Compose 的导航方法。

设置


要使用导航库,需将以下依赖项添加到你的 commonMain 源集中:

kotlin {// ...sourceSets {// ...commonMain.dependencies {// ...implementation("org.jetbrains.androidx.navigation:navigation-compose:2.8.0-alpha10")}// ...}
}

类型安全的导航。

从 1.7.0 版本开始,Compose 多平台在通用代码中支持如 Jetpack 文档所述的类型安全的导航。

示例项目

要查看 Compose 多平台导航库的实际使用情况,请查看 “ nav_cupcake projecticon-default.png?t=O83Ahttps://github.com/JetBrains/compose-multiplatform/tree/master/examples/nav_cupcake” 项目,该项目是由 Navigate between screens with Compose Compose 在安卓(Android)中实现屏幕间导航icon-default.png?t=O83Ahttps://developer.android.com/codelabs/basic-android-kotlin-compose-navigation#0的代码实验室(codelab)转换而来的。

与 Jetpack Compose 一样,要实现导航,你应当:

1:列出应包含在导航图中的路由List routes 。每条路由都必须是定义了路径的唯一字符串。

2:创建一个 NavHostController 实例NavHostController,将其作为主要的可组合属性来管理导航。

3:向你的应用添加一个 NavHost 可组合项:

从你之前定义的路由列表中选择起始目的地。

创建一个导航图,可以直接创建(作为创建 NavHost 的一部分),也可以通过编程方式使用 NavController.createGraph() 函数来创建。

每个后台栈条目(导航图中包含的每条导航路由)都实现了 LifecycleOwner 接口。在应用的不同屏幕之间进行切换时,其状态会从 “已恢复(RESUMED)” 变为 “已启动(STARTED)”,然后再变回去。“已恢复(RESUMED)” 状态也被描述为 “已稳定”:当新屏幕准备就绪且处于活动状态时,就认为导航已完成。有关 Compose 多平台中当前实现的详细信息,请参阅 “生命周期(Lifecycle)” 页面。

局限性;限制条件

与 Jetpack Compose 相比,Compose 多平台中导航功能的当前限制如下:

1:不支持深度链接Deep links(处理或跟踪深度链接)。

2:除安卓(Android)平台外,在任何其他平台上均不支持  BackHandlericon-default.png?t=O83Ahttps://developer.android.com/develop/ui/compose/libraries#handling_the_system_back_button 函数以及预测性返回手势。predictive back gesturesicon-default.png?t=O83Ahttps://developer.android.com/guide/navigation/custom-back/predictive-back-gesture 

第三方替代方案

例如在某个软件功能领域,如果官方提供的方案存在一些局限或者不能满足特定需求时,就可以去寻找由第三方开发者或团队所提供的其他可替代的解决方案来满足相应需求.

如果 Compose 多平台导航组件无法解决你的问题,还有一些第三方替代方案可供你选择:

Name

Description

Voyager

一种务实的导航方法。

Decompose

一种涵盖整个生命周期以及任何潜在依赖注入的高级导航方法。

Appyx

带有手势控制的模型驱动导航。

PreCompose

一种受 Jetpack 生命周期、视图模型、实时数据以及导航组件启发的导航和视图模型

Circuit

一种适用于具有导航和高级状态管理功能的 Kotlin 应用程序的、由 Compose 驱动的架构。

完整示例

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Arrangement.Absolute.Center
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifierimport androidx.navigation.NavHostControllerimport androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.BottomNavigation
import androidx.compose.material.BottomNavigationItem
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AccountBox
import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.Search
import androidx.compose.material3.HorizontalDivider
import androidx.compose.ui.Alignment
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import org.jetbrains.compose.resources.StringResource
import androidx.navigation.compose.rememberNavController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import kotlinmultiplatform.composeapp.generated.resources.*
import kotlinmultiplatform.composeapp.generated.resources.Res
import kotlinmultiplatform.composeapp.generated.resources.home
import kotlinmultiplatform.composeapp.generated.resources.mine
import kotlinmultiplatform.composeapp.generated.resources.order
import org.jetbrains.compose.resources.stringResource
import org.lxz.project.compose.demo.ScaffoldDemo.imageVectorobject NavigationApp {enum class MainTabsMenu(val title: StringResource) {HOME(title = Res.string.home),ORDER(title = Res.string.order),MINE(title = Res.string.mine),SEARCH(title = Res.string.search);}val homeIcon = Icons.Filled.Homeval orderIcon = Icons.Filled.Searchval mineIcon = Icons.Filled.AccountBox@Composable
fun MainNavigationApp(navController: NavHostController = rememberNavController()) {val currentRoute = navController.currentBackStackEntryAsState().value?.destination?.route// Get current back stack entryval backStackEntry by navController.currentBackStackEntryAsState()// Get the name of the current screenScaffold(topBar = {TopAppBar(modifier = Modifier.height(56.dp), // 设置顶部栏高度为56dp示例title = {Text(text = "My Awesome App")},// 右侧操作按钮(示例添加一个搜索按钮)actions = {IconButton(onClick = {navController.navigate(MainTabsMenu.SEARCH.name)}) {Icon(imageVector = imageVector, contentDescription = "Search")}})},bottomBar = {BottomNavigation(modifier = Modifier.fillMaxWidth()) {BottomNavigationItem(icon = { homeIcon },label = { Text(text = stringResource(MainTabsMenu.HOME.title)) },selected = currentRoute == MainTabsMenu.HOME.name,onClick = {navController.navigate(MainTabsMenu.HOME.name) {}},alwaysShowLabel = true)BottomNavigationItem(icon = { orderIcon },label = { Text(text = stringResource(MainTabsMenu.ORDER.title)) },selected = currentRoute == MainTabsMenu.ORDER.name,onClick = {navController.navigate(MainTabsMenu.ORDER.name) {}},alwaysShowLabel = true)BottomNavigationItem(icon = { mineIcon },label = { Text(text = stringResource(MainTabsMenu.MINE.title)) },selected = currentRoute == MainTabsMenu.ORDER.name,onClick = {navController.navigate(MainTabsMenu.MINE.name) {}},alwaysShowLabel = true)}}) { innerPadding ->NavHost(navController = navController,startDestination = MainTabsMenu.HOME.name,modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(innerPadding)) {composable(route = MainTabsMenu.HOME.name) {bottomMenuItem(MainTabsMenu.HOME)}composable(route = MainTabsMenu.ORDER.name) {bottomMenuItem(MainTabsMenu.ORDER)}composable(route = MainTabsMenu.MINE.name) {bottomMenuItem(MainTabsMenu.MINE)}composable(route = MainTabsMenu.SEARCH.name) {bottomMenuItem(MainTabsMenu.SEARCH)}}}}
}@Composable
fun bottomMenuItem(item: NavigationApp.MainTabsMenu) {Column(verticalArrangement = Arrangement.Center,horizontalAlignment = Alignment.CenterHorizontally,modifier = Modifier.fillMaxWidth().fillMaxHeight().background(Color.White),) {Text(textAlign = TextAlign.Center,text = stringResource(item.title),)}}

运行效果:


http://www.mrgr.cn/news/82162.html

相关文章:

  • 网络IP协议
  • MySQL 索引分类及区别与特点
  • PCL点云库入门——PCL库点云特征之点云法向量(NormalEstimation)及其可视化
  • Win11+WLS Ubuntu 鸿蒙开发环境搭建(二)
  • 沙箱模拟支付宝支付3--支付的实现
  • 算法解析-经典150(双指针、滑动窗口)
  • 智能工厂的设计软件 应用场景的一个例子:为AI聊天工具添加一个知识系统 之11 方案再探之2 项目文件(修改稿1)
  • Linux2.4.20顶层Makefile文件分析
  • 我的Java-Web进阶--Spring
  • CPT203 Software Engineering 软件工程 Pt.2 敏捷方法和需求工程(中英双语)
  • 计算机的错误计算(一百九十七)
  • Kubernetes第二天
  • Vue演练场基础知识(一)
  • Wireshark和科来网络分析系统
  • 掌握大数据处理利器:Flink 知识点全面总结【上】
  • C++ 设计模式:职责链模式(Chain of Responsibility)
  • pyside6总结
  • Docker新手:在tencent云上实现Python服务打包到容器
  • 【Unity3d】C#浮点数丢失精度问题
  • 【文献精读笔记】Explainability for Large Language Models: A Survey (大语言模型的可解释性综述)(二)
  • 1、pycharm、python下载与安装
  • 软件测试期末复习
  • 基于Python的社交音乐分享平台
  • 4.微服务灰度发布落地实践(消息队列增强)
  • C++ 设计模式:命令模式(Command Pattern)
  • AI与药学 | ChatGPT 在临床药学中的有效性以及人工智能在药物治疗管理中的作用