标签: android-jetpack-navigation

Compose-Navigation:在导航之前从堆栈中删除以前的可组合项

我正在使用compose-navigation(alpha09) 来处理可组合项之间的导航

我想在移动到下一个目的地时删除启动屏幕(我不希望按下后背返回启动屏幕)

以下尝试未按预期工作:

navHostController.navigate(Route.login.id) {
    navHostController.graph.clear()
}
Run Code Online (Sandbox Code Playgroud)
navHostController.navigate(Route.login.id)
navHostController.graph.clear()
Run Code Online (Sandbox Code Playgroud)
val currentDest = navHostController.currentDestination
navHostController.navigate(Route.login.id)
if (currentDest != null) {
   navHostController.graph.remove(currentDest)
}
Run Code Online (Sandbox Code Playgroud)

那么如何删除启动屏幕然后转到下一步呢?

android android-jetpack-navigation android-jetpack-compose jetpack-compose-navigation

65
推荐指数
5
解决办法
4万
查看次数

CreationExtras 必须具有“SAVED_STATE_REGISTRY_OWNER_KEY”的值

我正在尝试在使用 Jetpack Compose 构建的应用程序中实现导航,但是当我尝试从一个屏幕导航到另一个屏幕时,我得到:

java.lang.IllegalArgumentException:CreationExtras 必须有一个值SAVED_STATE_REGISTRY_OWNER_KEY

我在用着:

implementation "androidx.hilt:hilt-navigation-compose:1.0.0"
Run Code Online (Sandbox Code Playgroud)

这是代码:

if(viewModel.isAuthenticated) {
    navController.navigate(Screen.Profile.route)
}
Run Code Online (Sandbox Code Playgroud)

android kotlin android-jetpack-navigation android-jetpack-compose

51
推荐指数
6
解决办法
2万
查看次数

在 Jetpack Compose Navigation 中共享 viewModel

谁能建议如何在 Jetpack Compose Navigation 的不同部分中共享 ViewModel?

根据文档,viewModel 通常应该使用活动范围在不同的 compose 函数中共享,但如果在导航内部则不然。

这是我试图修复的代码。看起来我在导航内的两个部分中获得了两个不同的 viewModel:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            NavigationSystem()
        }
    }
}

@Composable
fun NavigationSystem() {
    val navController = rememberNavController()

    NavHost(navController = navController, startDestination = "home") {
        composable("home") { HomeScreen(navController) }
        composable("result") { ResultScreen(navController) }
    }
}

@Composable
fun HomeScreen(navController: NavController) {
    val viewModel: ConversionViewModel = viewModel()
    
    var temp by remember { mutableStateOf("") }
    val fahrenheit = temp.toIntOrNull() ?: 0

    Column(
        modifier = …
Run Code Online (Sandbox Code Playgroud)

android-viewmodel android-jetpack-navigation android-jetpack-compose

43
推荐指数
4
解决办法
3万
查看次数

Jetpack Compose Navigation - 将参数传递给 startDestination

我正在构建的应用程序使用带有路线的组合导航。挑战在于起始目的地是动态的。

这是一个最小的例子:

class MainActivity : ComponentActivity()
{
    override fun onCreate(savedInstanceState: Bundle?)
    {
        super.onCreate(savedInstanceState)

        setContent {
            val navController = rememberNavController()

            NavHost(
                navController = navController,
                startDestination = "dynamic/1", // doesn't work
                // startDestination = "static", // workaround
            ) {
                composable(
                    route = "dynamic/{$ARG_ID}",
                    arguments = listOf(navArgument(ARG_ID) { type = NavType.StringType }),
                ) {
                    val id = it.arguments?.getString(ARG_ID)
                    Text("dynamic route, received argument: $id!")
                }
                // part of the workaround
                // composable(
                //  route = "static",
                // ) {
                //  LaunchedEffect(this) {
                //      navController.navigate("dynamic/1") …
Run Code Online (Sandbox Code Playgroud)

android android-jetpack-navigation android-jetpack-compose android-navigation-graph

29
推荐指数
1
解决办法
1万
查看次数

Jetpack Compose NavHost 重组可组合多次

我发现可组合屏幕在 Navhost 导航期间多次重新组合,以下示例显示了我如何将导航与日志集成以识别函数被调用的次数,

internal sealed class Screen(val route: String) {
  object Splash : Screen("splash")
  object Login : Screen("login")
  object Credentials : Screen("credentials/{type}") {
    fun createRoute(type: String) = "credentials/$type"
  }
}

@Composable
fun HostNavGraph(
  modifier: Modifier = Modifier,
  startDestination: String = Splash.route,
) {
  val navController = rememberNavController()
  val vm: CredentialsViewModel = getViewModel()
  NavHost(navController = navController, startDestination = startDestination, modifier = modifier) {
    composable(route = Splash.route) {
      Log.e("composable", " Splash")
      SplashScreen(openLogin = {
        navController.navigate(Login.route)
      }, openRegistration = { type ->
        navController.navigate(Credentials.createRoute(type)) …
Run Code Online (Sandbox Code Playgroud)

android android-jetpack-navigation android-jetpack-compose jetpack-compose-navigation compose-recomposition

26
推荐指数
1
解决办法
5847
查看次数

使用Jetpack的Android导航组件销毁/重新创建的片段

我正在尝试在现有应用程序中使用Jetpack的体系结构组件实现导航

我有一个活动应用程序,其中主要片段(ListFragment)是项目列表。当前,当用户点击列表项时,通过会将第二个片段添加到堆栈中fragmentTransaction.add(R.id.main, detailFragment)。因此,当按下后盖时,DetailFragment会分离,然后ListFragment再次显示。

使用导航架构,这是自动处理的。而不是添加新的片段,而是替换了片段,因此片段视图被销毁,onDestroyView()onCreateView()在按下back来重新创建视图时被调用。

我知道这是与LiveDataViewModel一起使用的一种很好的模式,可以避免使用过多的内存,但是在我的情况下,这很烦人,因为该列表的布局很复杂,夸大了时间和CPU的消耗,还因为我需要保存列表的滚动位置并再次滚动到用户离开片段的相同位置。有可能,但似乎应该存在一个更好的方法。

我试图将视图保存在片段的私有字段中,onCreateView()如果已经存在,请重新使用它,但这似乎是一种反模式。

private View view = null;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    if (view == null) {
        view = inflater.inflate(R.layout.fragment_list, container, false);
        //...
    }

    return view;
}
Run Code Online (Sandbox Code Playgroud)

还有其他更优雅的方法来避免重新布局吗?

android android-fragments android-jetpack android-architecture-navigation android-jetpack-navigation

25
推荐指数
3
解决办法
3673
查看次数

使用导航组件将视图模型范围限定为多个片段(不是活动)

我正在使用导航组件,我希望在几个片段之间共享一个视图模型,但是当我离开片段时应该清除它们(因此没有将它们范围限定到活动中)我试图将一个活动放在多个片段中方法。我已经设法使用多个导航主机实现了这一点,并使用 getParentFragment 将片段范围限定到它,但这只会导致更多的问题不得不将片段包装在其他父片段中,失去后退按钮无缝工作和其他黑客来获得一些应该工作的东西很简单。有没有人有关于如何实现这一目标的好主意?我想知道我是否可以使用 getViewModelStore 的任何东西,鉴于下面的图像,我想将视图模型范围限定为 createCardFragment2 并在它之后的任何内容中使用它(addPredictions、editImageFragment 和其他我没有的)

顺便说一句,我不能只在 mainFragment 视图模型存储上调用 clear,因为这里还有其他不应清除的视图模型,我想我想要一种方法来告诉导航主机我知道的父片段应该是什么不是如果我从 mainFragment 或 cardPreviewFragment 导航,这将是一件事,或者一种使视图模型更新的方法

导航图

android android-fragments android-viewmodel android-jetpack android-jetpack-navigation

24
推荐指数
3
解决办法
7193
查看次数

Jetpack Compose:通过按钮关闭应用程序

NavController 无法以编程方式弹出堆栈中最新的 @Composable。即,如果它是根页面,则 popBackStack() 不起作用。因此,可以通过点击“关闭”按钮视图来关闭应用程序,并且只有硬件后退键允许离开应用程序。

示例:活动

class AppActivity : ComponentActivity() {
    override fun onCreate(state: Bundle?) {
        super.onCreate(state)
        setContent {
            val controller = rememberNavController()
            NavHost(controller, startDestination = HOME) {
                composable(HOME) { HomePage(controller) }
                ...
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

主页.kt

@Composable
fun HomePage(controller: NavController) {
    Button(onClick = {
        controller.popBackStack()
    }) {
        Text("Exit")
    }
}
Run Code Online (Sandbox Code Playgroud)

问题:

如果使用 Compose Navigation,如何在 onClick 处理程序中关闭应用程序。

kotlin android-jetpack-navigation android-jetpack-compose

23
推荐指数
1
解决办法
3万
查看次数

如何在 Jetpack Compose 中强制某些屏幕的方向?

有了jetpack compose navigation,我想它可能会成为一个单一的活动应用程序。如何仅对某些可组合项(屏幕)强制定向?假设我只想在播放视频而不是其他屏幕时强制横向?没有导航,可以在清单中声明方向,但使用导航,我们可以在可组合级别指定这一点?

android android-jetpack-navigation android-jetpack-compose

21
推荐指数
1
解决办法
9818
查看次数

片段 XXX {} 未与片段管理器关联

我开始在我的应用程序中使用导航组件,但我面临以下问题。我的第一个片段是 LoginFragment。登录成功后,显示mainFragment。我希望当用户在 mainFragment 上并按后退按钮不返回到 loginFragment 时。为此,我在 nav_graph 中添加了这两行:app:popUpTo="@+id/lovable_app_navigation"并且app:popUpToInclusive="true"效果很好。这是我的导航图:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  xmlns:tools="http://schemas.android.com/tools"
  android:id="@+id/app_navigation"
  app:startDestination="@id/loginFragment">

  <fragment
    android:id="@+id/loginFragment"
    android:name="com.xxx.LoginFragment"
    android:label="LoginFragment"
    tools:layout="@layout/login_fragment">
    <action
      android:id="@+id/dashboard_action"
      app:destination="@id/mainFragment"
      app:launchSingleTop="true"
      app:popUpTo="@+id/app_navigation"
      app:popUpToInclusive="true"/>
  </fragment>

  <fragment
    android:id="@+id/mainFragment"
    android:name="com.xxx.MainFragment"
    android:label="MainFragment"
    tools:layout="@layout/main_fragment">
       <action
      android:id="@+id/logout_action"
      app:destination="@id/loginFragment"
      app:launchSingleTop="true"
      app:popUpTo="@+id/app_navigation"
      app:popUpToInclusive="true"/>
  </fragment>

  <action
    android:id="@+id/action_global_loginFragment"
    app:destination="@id/loginFragment" />
</navigation>
Run Code Online (Sandbox Code Playgroud)

问题是,一段时间后,当我的会话过期时,用户在应用程序中的哪个位置、在哪个片段中都无关紧要,我必须在所有堆栈上显示 LoginFragment。我为此创建了一个全局操作action_global_loginFragment。问题是,当我导航到 LoginFragment 时,出现此错误:

java.lang.IllegalStateException: Fragment LoginFragment{1d6bd24 (829a6832-3480-4bcb-a3f6-7e2ba214d3ca)} not associated with a fragment manager.
Run Code Online (Sandbox Code Playgroud)

如果我删除popUpTo并且popUpToInclusive它工作正常,但是后退按钮功能受到影响,它会从 mainFragment 返回到 loginFragment。知道如何解决这个问题吗?提前致谢。

navigation android android-jetpack-navigation

19
推荐指数
2
解决办法
1万
查看次数