我正在使用带有底部导航的Jetpack导航version 1.0.0-alpha04。它可以工作,但导航不能正确进行。例如,如果我有tab A和tab B,从tab A转到Page C,然后从那里转到tab B并再次返回到tab A,我将在tab A而不是page C中看到根片段,这并不是我所期望的。
我正在寻找一个解决方案,让每个选项卡有一个不同的堆栈,这样当我返回到每个选项卡时,每个选项卡的状态都是保留的,而且我不喜欢将所有这些片段保留在内存中,因为它对性能有很坏的影响,在jetpack导航之前,我使用了这个库https://github.com/ncapdevi/FragNav,它做了什么,现在我正在寻找与jetpack导航相同的东西。
发布于 2018-09-03 17:06:08
EDIT 2:虽然仍然没有一流的支持(在撰写本文时),但谷歌现在已经更新了他们的示例,说明了他们认为目前应该如何解决这个问题:https://github.com/googlesamples/android-architecture-components/tree/master/NavigationAdvancedSample
主要原因是您只使用一个NavHostFragment来容纳整个应用程序的后端堆栈。
解决方案是每个选项卡都应该有自己的后端堆栈。
FrameLayout.NavHostFragment,并包含其自己的导航图,以便使每个标签片段具有自己的后堆栈。BottomNavigationView.OnNavigationItemSelectedListener添加到BottomNavigtionView以处理每个标签片段的可见性这也照顾到了你的"...I不喜欢在内存中保存所有这些片段...“,因为默认情况下,使用NavHostFragment的导航使用fragmentTransaction.replace(),也就是说,你总是只有和你的NavHostFragment一样多的片段,其余的只是在你的导航图的后栈中。
谷歌编辑:正在开发一个原生实现的https://issuetracker.google.com/issues/80029773#comment25
更多详细信息
假设您有一个带有两个菜单选项的BottomNavigationView:Dogs和Cats。
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/dogMenu"
.../>
<item android:id="@+id/catMenu"
.../>
</menu>然后你需要两个导航图,比如dog_navigation_graph.xml和cat_navigation_graph.xml。
dog_navigation_graph可能如下所示
<navigation
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/dog_navigation_graph"
app:startDestination="@id/dogMenu">
</navigation>以及对应于cat_navigation_graph的。
在activity_main.xml中,添加2个NavHostFragment%s
<FrameLayout
android:id="@+id/frame_dog"
...>
<fragment
android:id="@+id/dog_navigation_host_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="androidx.navigation.fragment.NavHostFragment"
app:navGraph="@navigation/dog_navigation_graph"
app:defaultNavHost="true"/>
</FrameLayout>然后在下面为您的猫NavHostFragment添加相应的。在cat框架布局上,设置android:visibility="invisible"
现在,在你的MainActivity的onCreateView中,你可以
bottom_navigation_view.setOnNavigationItemSelectedListener { item ->
when (item.itemId) {
R.id.dogMenu -> showHostView(host = 0)
R.id.catMenu -> showHostView(host = 1)
}
return@setOnNavigationItemSelectedListener true
}showHostView()所做的就是切换包装NavHostFragment的FrameLayout的可见性。因此,请确保以某种方式保存它们,例如在onCreateView中
val hostViews = arrayListOf<FrameLayout>() // Member variable of MainActivity
hostViews.apply {
add(findViewById(R.id.frame_dog))
add(findViewById(R.id.frame_cat))
}现在很容易切换哪个hostViews应该是可见的和不可见的。
发布于 2021-06-01 12:01:00
Android团队已经解决了这个问题,在最新的2.4.0-alpha01版本中,现在可以在没有任何解决方法的情况下支持多个backstacks以及底部导航。
https://developer.android.com/jetpack/androidx/releases/navigation
发布于 2021-03-31 14:07:48
首先,我想对@Algar的答案进行编辑。您要隐藏的框架应该具有android:visibility="gone"而不是invisible。这样做的原因是在你的主布局中,你会有这样的东西:
<LinearLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ui.activity.MainActivity">
<include
android:id="@+id/toolbar"
layout="@layout/toolbar_base" />
<FrameLayout
android:id="@+id/frame_home"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
>
<fragment
android:id="@+id/home_navigation_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/home_nav" />
</FrameLayout>
<FrameLayout
android:id="@+id/frame_find"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:visibility="gone">
<fragment
android:id="@+id/find_navigation_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/find_nav" />
</FrameLayout>
...
</LinearLayout>如果将main包装在LinearLayout中,将frame设置为不可见仍会使该frame有效,因此main将不会出现。
其次,您应该创建一个NavHostFragment实例(即: curNavHostFragment)来跟踪在单击BottomNavigation中的选项卡时哪个NavHostFragment是可见的。注意:当活动被配置的更改破坏时,您可能希望恢复此curNavHostFragment。这是一个示例:
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
//if this activity is restored from previous state,
//we will have the ItemId of botnav the has been selected
//so that we can set up nav controller accordingly
switch (bottomNav.getSelectedItemId()) {
case R.id.home_fragment:
curNavHostFragment = homeNavHostFragment;
...
break;
case R.id.find_products_fragment:
curNavHostFragment = findNavHostFragment;
...
break;
}
curNavController = curNavHostFragment.getNavController();https://stackoverflow.com/questions/51707889
复制相似问题