我的目标是在复杂的导航架构中以最好的方式理解和使用导航组件(我想)。
为了创建全局上下文,我使用了一个包含5个项目的主BottomNavigationBar。对于片段关联的管理,我使用了谷歌给出的例子:https://github.com/googlesamples/android-architecture-components/tree/master/NavigationAdvancedSample。
但我的情况要复杂得多,不仅仅是一个底部的横杆。在由底部栏启动的一个片段的一个目的地中,我有另一个RecyclerView菜单和一个片段容器来在片段之间导航。我把我的主要图表的重要部分放在这里:
<?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/main"
app:startDestination="@id/mainFragment">
<fragment
android:id="@+id/mainFragment"
android:name="com.exemple.fragment.MainFragment"
android:label="@string/main_label"
tools:layout="@layout/mainFragment">
<action
android:id="@+id/action_mainFragment_to_goScreen"
app:destination="@id/goScreen">
</action>
</fragment>
<fragment
android:id="@+id/goScreen"
android:name="com.exemple.fragment.GoFragment"
android:label="@string/goLabel"
tools:layout="@layout/fragment_go">
<action
android:id="@+id/action_goScreen_to_mainFragment"
app:destination="@id/mainFragment" />
<argument
android:name="arg1"
app:argType="com.exemple.customType"
android:defaultValue="@null"
app:nullable="true" />
<argument
android:name="arg2"
app:argType="string"
android:defaultValue="@null"
app:nullable="true" />
</fragment>
</navigation>下面是开始这个图形的带有底栏的xml:
<?xml version="1.0" encoding="utf-8"?>
<layout 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"
tools:context="com.exemple.MainActivity">
<RelativeLayout
android:id="@+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/fake_toolbar"
android:layout_width="0dp"
android:layout_height="0dp"/>
<androidx.fragment.app.FragmentTabHost
android:id="@+id/main_host_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/bottom_navigation" />
<!-- navigation bottom -->
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:layout_alignParentBottom="true"
android:background="@color/navigationBarColor"
app:itemIconTint="@color/textColorNavigationBar"
app:itemTextColor="@color/textColorNavigationBar"
app:menu="@menu/menu_bottom_navigation" />
</RelativeLayout>
</layout>下面是与go片段(目的地)对应的图的示例:
<?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/go"
app:startDestination="@id/firstGoFragment">
<action android:id="@+id/action_to_firstGoFragment"
app:destination="@id/firstGoFragment"/>
<fragment
android:id="@+id/firstGoFragment"
android:name="com.exemple.go.firstGoFragment"
android:label="@string/firstGoFragmentLabel"
tools:layout="@layout/firstGoFragment" >
</fragment>
<action android:id="@+id/action_to_secondFragment"
app:destination="@id/secondFragment"/>
<fragment
android:id="@+id/secondFragment"
android:name="com.exemple.go.SecondFragment"
android:label="@string/secondFragmentLabel"
tools:layout="@layout/secondFragment" >
</fragment>
</navigation>关联xml是:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorGreyLight"
android:clickable="true"
android:focusable="true">
<RelativeLayout
android:id="@+id/linearLayout3"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/quit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginStart="16dp"
android:paddingBottom="15dp"
android:paddingEnd="15dp"
android:paddingTop="15dp"
app:srcCompat="@drawable/ic_quit_white" />
<com.teedji.mobeelity.custom.CustomTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="@string/go"
android:textColor="@color/colorWhite"
android:textSize="17sp"
android:textStyle="bold" />
</RelativeLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/goMenu"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@color/colorWhite"
android:overScrollMode="never"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/linearLayout3" />
<!-- include fragment child container -->
<fragment
android:id="@+id/go_nav_host_fragment_container"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/goMenu"
app:navGraph="@navigation/go"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>现在,要导航到go屏幕,我只需使用
findNavController().navigate(MainFragmentDirections.actionMainFragmentToGoScreen(arg1, arg2))或
findNavController().navigate(R.id. action_mainFragment_to_goScreen)但是当我在Go片段上时,我使用findNavController()找到的navController仍然是mainFragment。所以navigate()函数没有找到动作id。为了解决这个问题,我不得不在GoFragment中更改navHost编程,如下所示:
override fun onCreate(savedInstanceState: Bundle?) {
Log.i(LOG_TAG, "onCreate")
super.onCreate(savedInstanceState)
if( fragmentManager != null ) {
// If the Nav Host fragment exists, return it
val existingFragment = fragmentManager!!.findFragmentByTag(FRAGMENT_TAG) as NavHostFragment?
existingFragment?.let { navHostGoFragment = it }
// Otherwise, create it and return it.
if ( navHostGoFragment == null) {
navHostGoFragment = NavHostFragment.create(R.navigation.go)
fragmentManager!!.beginTransaction()
.add(R.id.go_nav_host_fragment_container, navHostGoFragment!!, FRAGMENT_TAG)
.commit()
}
}else {
Log.e(LOG_TAG, "fragmentManager is null so I can't find the fragment host")
}
}然后使用navHostGoFragment!!.navController.navigate(R.id.action_to_firstGoFragment)在新的容器中导航,但是这样做,我的firstFragment被创建了两次(我可以在我的日志中看到它),这会产生一些问题,例如Cannot add the same observer with different lifecycles (我通过添加
if (model.getLiveData().hasObservers()) {
model.getLiveData().removeObserver(observer)
}在此之前
model.getLiveData().observe(viewLifecycleOwner, observer))但是我认为我没有像我应该做的那样做导航部分……
你能提供任何帮助,让这项工作更高效,更稳定吗?
发布于 2019-10-03 07:45:47
如果你使用的是Kotlin Android扩展或findViewById(R.id.go_nav_host_fragment_container).findNavController().navigate(),试着使用go_nav_host_fragment_container.findNavController().navigate(),看看它是否工作。
https://stackoverflow.com/questions/57970307
复制相似问题