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

具有多个顶级目的地和后退键行为的导航图

桑宇
2023-03-14

当我在导航图中有多个顶级目的地,并且当我点击后退键完成我的应用程序时,除了startDestination之外的那些目的地不会完成,而是弹出startDestination片段。

  • FragmentA(开始目的地)-

我试过应用程序:popUpTo="@id/nav_graph"和/或应用程序:popUpTo包容="true"但徒劳无功。

活动:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);

        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);

        DrawerLayout drawerLayout = findViewById(R.id.drawer_layout);

        AppBarConfiguration appBarConfiguration =
                new AppBarConfiguration.Builder(R.id.fragmentA, R.id.fragmentB, R.id.fragmentC)
                        .setOpenableLayout(drawerLayout)
                        .build();

        NavigationView navView = findViewById(R.id.nav_view);
        NavigationUI.setupWithNavController(navView, navController);

        Toolbar toolbar = findViewById(R.id.toolbar);
        NavigationUI.setupWithNavController(
                toolbar,
                navController,
                appBarConfiguration
        );
    }
}

layout.xml:

<?xml version="1.0" encoding="utf-8"?>
<!-- Use DrawerLayout as root container for activity -->
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <!-- Layout to contain contents of navigation_view body of screen (drawer will slide over this) -->
    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:background="?attr/colorPrimary"
            android:minHeight="?attr/actionBarSize"
            android:theme="@style/AppTheme.AppBarOverlay"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

        <fragment
            android:id="@+id/nav_host_fragment"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:defaultNavHost="true"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/toolbar"
            app:navGraph="@navigation/nav_graph" />
    </androidx.constraintlayout.widget.ConstraintLayout>

    <!-- Container for contents of drawer - use NavigationView to make configuration easier -->
    <com.google.android.material.navigation.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/navigation_header"
        app:menu="@menu/navigation_view" />

</androidx.drawerlayout.widget.DrawerLayout>

nav_graph:

<?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"
    android:id="@+id/nav_graph"
    app:startDestination="@id/fragmentA">

    <fragment
        android:id="@+id/fragmentA"
        android:name="com.stackoverflow.FragmentA"
        android:label="@string/fragmentA">
        <argument
            android:name="message"
            android:defaultValue="(no message)"
            app:argType="string" />
    </fragment>

    <action
        android:id="@+id/toFragmentAWithMessage1"
        app:destination="@id/fragmentA">
        <argument
            android:name="message"
            android:defaultValue="message 1"
            app:argType="string" />
    </action>

    <action
        android:id="@+id/toFragmentAWithMessage2"
        app:destination="@id/fragmentA">
        <argument
            android:name="message"
            android:defaultValue="message 2"
            app:argType="string" />
    </action>

    <fragment
        android:id="@+id/fragmentB"
        android:name="com.stackoverflow.navigationui.FragmentB"
        android:label="@string/fragmentB">
        <argument
            android:name="message"
            android:defaultValue="(no message)"
            app:argType="string" />
    </fragment>

    <action
        android:id="@+id/toFragmentBWithMessage1"
        app:destination="@id/fragmentB">
        <argument
            android:name="message"
            android:defaultValue="message 1"
            app:argType="string" />
    </action>

    <action
        android:id="@+id/toFragmentBWithMessage2"
        app:destination="@id/fragmentB">
        <argument
            android:name="message"
            android:defaultValue="message 2"
            app:argType="string" />
    </action>

    <fragment
        android:id="@+id/fragmentC"
        android:name="com.stackoverflow.FragmentC"
        android:label="@string/fragmentC">
        <argument
            android:name="message"
            android:defaultValue="(no message)"
            app:argType="string" />
    </fragment>

    <action
        android:id="@+id/toFragmentCWithMessage1"
        app:destination="@id/fragmentC">
        <argument
            android:name="message"
            android:defaultValue="message 1"
            app:argType="string" />
    </action>

    <action
        android:id="@+id/toFragmentCWithMessage2"
        app:destination="@id/fragmentC">
        <argument
            android:name="message"
            android:defaultValue="message 2"
            app:argType="string" />
    </action>

</navigation>

我知道重写OnBackPressedCallback是一种变通方法。

public class FragmentB extends Fragment {

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        requireActivity().getOnBackPressedDispatcher().addCallback(new OnBackPressedCallback(true) {
            @Override
            public void handleOnBackPressed() {
                remove();
                requireActivity().finish();
            }
        });
    }
}

还有更根本的解决办法吗?

共有1个答案

唐照
2023-03-14

只需删除或设置false的应用程序:defaultNavHost属性的NavHostFrach的

<fragment
    android:id="@+id/nav_host_fragment"
    android:name="androidx.navigation.fragment.NavHostFragment"
    app:defaultNavHost="false"
    />

以编程方式与导航组件交互

请注意,setPrimaryNavigationFragment(finalHost)允许您的NavHost拦截系统返回按钮。您还可以通过添加app:defaultNavHost=“true”在NavHost XML中实现此行为。

setPrimaryNavigationFra片段

作为主片段管理器中当前活动的片段。

将首先调用主导航片段的子FragmentManager来处理委派的导航操作,例如FragmentManager。popbackbackstack()如果没有提供ID或事务名称给pop to。片段系统之外的导航操作可以选择将这些操作委派给FragmentManager返回的主导航片段。getPrimaryNavigationFragment()

由于您将app:defaultNavHost设置为true,因此您的NavHost会截获back键并弹出startDestination片段。

 类似资料:
  • 我在空闲时间实现了一个android应用程序(在Kotlin中,但这与问题无关),我尝试使用android jetpack和新的库。我有一个带有导航抽屉的活动。我试着遵循sunflower应用程序示例。它在主活动中使用以下组合来启用导航抽屉后面的逻辑: 注意:当在抽屉菜单中单击时,它会自动导航到正确的片段,并关闭抽屉,保持它们被选中等。所有的样板代码。这很整洁,也很有效。据我所知,抽屉菜单项的ID

  • 请帮帮我,我已经绕了几个小时了!我设置了一个抽屉菜单和一个工具栏(见下面的代码),我无法让返回/回家功能工作,因为单击它会导致打开抽屉。 这是我的主要活动,在OnCreate期间调用。 以下是我片段的OnCreateView方法中的内容。。。 抽屉菜单工作正常。更改工具栏的标题工作正常。汉堡包图标在片段中更改为向后箭头就好了...然而,每次我按下向后箭头,它都会打开抽屉...有点像抽屉的听众在向后

  • 假设我有一个Hazelcast映射,它在配置文件中定义了86400秒的TTL,在初始化映射时使用。 但是,我在代码中观察到在map中添加条目时(使用map.put())-还会为所有单个值传递另一个TTL。 关键级别的TTL会被认为是高级的,而TTL和map级别会被忽略吗?

  • 问题内容: 我需要一个数据结构,其行为类似于Map,但是使用多个(不同类型的)键来访问其值。 (让我们不太笼统,假设有两个键) 键保证是唯一的。 就像是: 使用以下方法: 你有什么建议吗? 我唯一能想到的是: 编写一个内部使用两个Maps的类。 编辑 有人建议我使用元组,一对或类似键作为Java Map的键,但是这对我来说不起作用: 如上所述,我必须只能通过两个键之一来搜索值指定。 映射使用键的哈

  • 我有一个有两个阶段的Dockerfile;第一阶段从源代码构建一个react应用程序,第二阶段复制构建并添加一个NGINX服务器: 我也在使用gitlab-ci,我希望有多个阶段:构建、测试和部署。但是我不知道如何将构建和测试阶段分开,因为我使用的是多阶段的DockerFile。问题是所有的JS测试(对于React)都需要在“Yarn build”执行之前运行,并且build被复制到seconds

  • 我已经开始使用新的导航组件,我真的很喜欢它!不过,我确实有一个问题——当我在图形的起始目的地时,我应该如何处理后退按钮? 这是我现在使用的代码: 当我在图表上的任何地方时,它都工作得很好,它会将我发回,但当我在开始时-应用程序崩溃,因为Backback是空的。 这一切对我来说都有意义,我只是不知道如何处理。 虽然我可以检查当前片段的ID是否与我知道是图的根的ID相同,但我正在寻找一个更优雅的解决方