当前位置: 首页 > 知识库问答 >
问题:

如何以编程方式更改导航图的起始目标?

公羊安怡
2023-03-14

基本上,我有以下导航图:

我想在到达后立即将导航图中的起点更改为片段2(以防止在按下后退按钮时返回到片段1,就像启动屏幕一样)。

这是我的代码:

navGraph = navController.getGraph();
navGraph.setStartDestination(R.id.fragment2);
navController.setGraph(navGraph);

但是,显然它不工作,它回到片段1后按后退按钮。

我做错了吗?还有其他解决办法吗?

共有3个答案

仰经武
2023-03-14

在主要活动中。kt

    val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
    val inflater = navHostFragment.navController.navInflater
    val graph = inflater.inflate(R.navigation.booking_navigation)

    if (isTrue){
        graph.startDestination = R.id.DetailsFragment
    }else {
        graph.startDestination = R.id.OtherDetailsFragment
    }

    val navController = navHostFragment.navController
    navController.setGraph(graph, intent.extras)

从导航图中删除startDestination。xml

?xml version="1.0" encoding="utf-8"?>
<!-- app:startDestination="@id/oneFragment" -->

<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/navigation_main">

  <fragment
    android:id="@+id/DetailFragment"
    android:name="DetailFragment"
    android:label="fragment_detail"
    tools:layout="@layout/fragment_detail"/>
  <fragment
    android:id="@+id/OtherDetailFragment"
    android:name="OtherDetailFragment"
    android:label="fragment_other_detail"
    tools:layout="@layout/fragment_other_detail"/>
</navigation>
邢献
2023-03-14

我找到了一个解决方案,但它很难看。我想这是alpha库的预期,但我希望谷歌能简化/修复这个问题,因为这是一个非常流行的导航模式。

亚历克西的解决方案对我不起作用。我的问题是,我的操作栏上显示了向上箭头:

NavigationUI。setupActionBarWithNavController(这是navController)

如果我按照Alexey的建议去做,我的新起始片段仍然有一个箭头指向我的初始起始片段。如果我按下那个向上箭头,我的应用程序就会重新启动,转换到自身(新的开始片段)

以下是我想要的代码:

  • 片段#1是我的应用程序最初启动的地方
  • 我可以在片段#1中执行身份验证检查,然后通过编程将开始更改为片段#2
  • 一旦进入片段#2,就没有向上箭头,按下后退按钮不会将您带到片段#1

下面是实现这一点的代码。在我的活动的onCreate中:

// Setup the toolbar
val toolbar = findViewById<Toolbar>(R.id.toolbar)
setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(false)

// Configure the navigation
val navHost = nav_host_fragment as NavHostFragment
graph = navHost.navController
        .navInflater.inflate(R.navigation.nav_graph)
graph.startDestination = R.id.welcomeFragment

// This seems to be a magical command. Not sure why it's needed :(
navHost.navController.graph = graph

NavigationUI.setupActionBarWithNavController(this, navHost.navController)

并且还:

fun makeHomeStart(){
    graph.startDestination = R.id.homeFragment
}

然后根据Alexey的建议,在片段#1的OnActivity Created中:

override fun onActivityCreated(savedInstanceState: Bundle?) {
    ...

    // Check for user authentication
    if(sharedViewModel.isUserAuthenticated()) {

        (activity as MainActivity).makeHomeStart() //<---- THIS is the key
        val navOptions = NavOptions.Builder()
                .setPopUpTo(R.id.welcomeFragment, true)
                .build()
        navController.navigate(R.id.action_welcomeFragment_to_homeFragment,null,navOptions)

    } else {
        navController.navigate(R.id.action_welcomeFragment_to_loginFragment)
    }
}

关键代码是:(活动作为MainActivity)。makeHomeStart(),它只是在活动中运行一个方法来更改图形startDestination。我可以把它清理干净,把它变成一个界面,但我会等待谷歌,希望他们能改进整个html" target="_blank">过程。对我来说,方法“setPoputto”的命名似乎很糟糕,而且你对从图中删除的片段进行命名并不直观。我也很奇怪,他们在导航选项上做了这些改变。我认为导航选项只与它们所连接的导航操作有关。

我甚至不知道navHost是什么。导航控制器。graph=graph有,但没有它,向上箭头返回:(

我正在使用导航1.0.0-alpha06。

岳浩穰
2023-03-14

当你有这样的导航图:

<fragment
    android:id="@+id/firstFragment"
    android:name="com.appname.package.FirstFragment" >
    <action
        android:id="@+id/action_firstFragment_to_secondFragment"
        app:destination="@id/secondFragment" /> 
</fragment>

<fragment
    android:id="@+id/secondFragment"
    android:name="com.appname.package.SecondFragment"/>

如果要导航到第二个片段并使其成为图形的根,请指定下一个NavOptions

NavOptions navOptions = new NavOptions.Builder()
        .setPopUpTo(R.id.firstFragment, true)
        .build();

并将其用于导航:

Navigation.findNavController(view).navigate(R.id.action_firstFragment_to_secondFragment, bundle, navOptions);

setPoputo(int destinationId,含布尔值)-导航前弹出到给定的目的地。这会从后堆栈中弹出所有不匹配的目标,直到找到该目标。

destinationId-要弹出的目的地,清除所有中间的目的地。

包含-也可以从后栈弹出给定的目标。

<fragment
    android:id="@+id/firstFragment"
    android:name="com.appname.package.FirstFragment" >
<action
    android:id="@+id/action_firstFragment_to_secondFragment"
    app:destination="@id/secondFragment"
    app:popUpTo="@+id/firstFragment"
    app:popUpToInclusive="true" /> 
</fragment>

<fragment
    android:id="@+id/secondFragment"
    android:name="com.appname.package.SecondFragment"/>

然后在你的代码上:

findNavController(fragment).navigate(
    FirstFragmentDirections.actionFirstFragmentToSecondFragment())

弃用:已弃用NavOptions中操作和关联API的clearTask属性。

资料来源:https://developer.android.com/jetpack/docs/release-notes

如果您想将根片段更改为片段2(例如,按下片段2上的后退按钮后,您将退出应用程序),您应该将下一个属性添加到操作目的地

app:clearTask="true"

从另一个角度来看:

<fragment
    android:id="@+id/firstFragment"
    android:name="com.appname.package.FirstFragment"
    android:label="fragment_first" >
    <action
        android:id="@+id/action_firstFragment_to_secondFragment"
        app:destination="@id/secondFragment"
        app:clearTask="true" /> 
</fragment>

<fragment
    android:id="@+id/secondFragment"
    android:name="com.appname.package.SecondFragment"
    android:label="fragment_second"/>

我已经添加了app: clearWork="true"到操作。


现在,当您执行从片段1片段2的导航时,使用下一个代码:

Navigation.findNavController(view)
        .navigate(R.id.action_firstFragment_to_secondFragment);
 类似资料:
  • 问题内容: 我有一个带有标题的导航栏。当我双击文本以将其重命名时,它实际上说这是一个导航项,所以可能就是这样。 我正在尝试使用代码来更改文本,例如: 那显然不是我的代码,只是显示了它是如何工作的。 因此,每当我按下按钮时,我都希望标题更改。 问题答案: 您可以通过更改显示的视图控制器的标题来更改标题: 通常,这是在视图控制器上加载视图时完成的: 但是,这仅在将视图控制器嵌入UINavigation

  • 我正在使用底部导航视图并希望以编程方式更改项目。有5个项目,当我设置第四个项目时,第一个项目仍然处于活动状态。

  • 问题内容: 如何以编程方式更改ActionBar中的MenuItem图标?我尝试使用 但这不起作用。这是我的代码: 主要活动 main.xml activity_main 这是我跑步后遇到的例外: 问题答案: 您不能在onCreate()的菜单项上使用findViewById(),因为菜单布局尚未膨胀。您可以创建一个全局Menu变量,并在onCreateOptionsMenu()中对其进行初始化,

  • 问题内容: 我使用了Android Studio中提供的Navigation Drawer模板。在我的活动布局中,我有以下代码: 我需要以编程方式更改面板的宽度。我认为更改它的正确区域是: 但是我不明白如何实现我的目标。 / 更新 / 抽屉面板的图标未显示在操作栏中 那就是selectItem方法 问题答案: 基于从Navigation Drawer模板生成的代码,可以通过将代码添加到Naviga

  • 我尝试通过主题或编程方式更改导航栏的颜色。 以下是我到目前为止所做的尝试: 在样式v21中: 以编程方式: 问题是:它在Nexus设备(Android 7.1.1)上运行得很好,但在LG Q6上运行得不好(同样适用于Android 7.1.1)。 我认为有办法做到这一点(因为Youtube应用程序有自己的导航栏颜色),但我不知道怎么做。 我也尝试了几乎所有的东西,这里,这里,这里和这里,都没有成功

  • 问题内容: 描述性示例: 登录屏幕,用户点击“登录”按钮,执行请求,UI显示等待指示器,然后在成功响应后,我想自动将用户导航到下一个屏幕。 如何在SwiftUI中实现这种自动转换? 问题答案: 成功登录后,可以使用登录视图替换下一个视图。例如: 您应该在数据模型中处理登录过程,并使用绑定(例如)传递到视图。 注意: 在Xcode中 11.0版测试4 ,以符合协议 “BindableObject”