TL DR:
Одно приложение Activity для планшета, необходимо работать с пользовательским меню.
A Фрагмент содержит пользовательское меню и вложенный NavHostFragment
для управления навигацией между дочерними фрагментами.
- Необходимо определить каждый отдельный переход между дочерними фрагментами. Фрагмент: A-> B, A -> C, B -> A, B -> C, C -> B, C -> A,
- Необходимо вручную назначать каждый щелчок меню с соответствующим переходом.
- Взгляды неоптимальный, так как в настоящем меню содержится около 10+ пунктов.
Есть ли лучший способ справиться с этим?
Подробно:
Это приложение предназначено для планшетов, и поскольку Material Rail в данный момент недоступен, а Navigation Drawer не удовлетворяет нашего дизайнера, поэтому мне нужно работать с пользовательским меню.
Приложение довольно простое. От LoginFragment
будет go до MainNavFragment
, которые содержат настраиваемую строку меню слева и вложенную NavHostFragment
справа для обработки навигации по всем дочерним фрагментам. Все они размещены в одном действии.
Это макет для MainActivity
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.MainActivity">
<fragment
android:id="@+id/am_nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
....
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>
Это родительский элемент nav_graph
:
<navigation
android:id="@+id/nav_graph"
app:startDestination="@id/loginFragment">
<fragment
android:id="@+id/loginFragment"
android:name=".ui.login.LoginFragment"
android:label="fragment_login"
tools:layout="@layout/fragment_login" >
<action
android:id="@+id/action_loginFragment_to_mainNavFragment"
app:destination="@id/mainNavFragment"
app:popUpTo="@id/loginFragment"
app:popUpToInclusive="true"/>
</fragment>
<fragment
android:id="@+id/mainNavFragment"
android:name=".ui.MainNavFragment"
android:label="MainNavFragment" />
</navigation>
Это макет для MainNavFragment
, в котором размещается вложенный NavHostFragment
:
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.MainNavFragment">
<include
android:id="@+id/fmn_nav_bar"
layout="@layout/layout_main_nav_bar"
.../>
<fragment
android:id="@+id/fmn_nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment
...
app:defaultNavHost="true"
app:navGraph="@navigation/main_screen_nav_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>
Это вложенный main_screen_nav_graph
, я должен определить каждый переход между каждым дочерним фрагментом, A-> B, A -> C, B-> A, B -> C , C -> B, C -> A:
<navigation
android:id="@+id/main_screen_nav_graph"
app:startDestination="@id/vitalFragment">
<fragment
android:id="@+id/vitalFragment"
android:name=".ui.vital.VitalFragment"
android:label="VitalFragment" >
<action
android:id="@+id/action_vitalFragment_to_labResultFragment"
app:destination="@id/labResultFragment" />
<action
android:id="@+id/action_vitalFragment_to_medicalTestFragment"
app:destination="@id/medicalTestFragment" />
</fragment>
<fragment
android:id="@+id/medicalTestFragment"
android:name=".ui.medical_test.MedicalTestFragment"
android:label="MedicalTestFragment" >
<action
android:id="@+id/action_medicalTestFragment_to_labResultFragment"
app:destination="@id/labResultFragment" />
<action
android:id="@+id/action_medicalTestFragment_to_vitalFragment"
app:destination="@id/vitalFragment" />
</fragment>
<fragment
android:id="@+id/labResultFragment"
android:name=".ui.lab_result.LabResultFragment"
android:label="LabResultFragment" >
<action
android:id="@+id/action_labResultFragment_to_vitalFragment"
app:destination="@id/vitalFragment" />
<action
android:id="@+id/action_labResultFragment_to_medicalTestFragment"
app:destination="@id/medicalTestFragment" />
</fragment>
</navigation>
Вот как я управляю навигацией из меню:
class MainNavFragment : BaseFragment() {
private lateinit var nestedNavController: NavController
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_main_nav, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val fragmentContainer = view.findViewById<View>(R.id.fmn_nav_host_fragment)
nestedNavController = Navigation.findNavController(fragmentContainer)
setupNavigationBar()
}
private fun setupNavigationBar() {
lmnb_vital_iv.setOnClickListener {
when (nestedNavController.currentDestination?.id) {
R.id.medicalTestFragment -> nestedNavController.navigate(R.id.action_medicalTestFragment_to_vitalFragment)
R.id.labResultFragment -> nestedNavController.navigate(R.id.action_labResultFragment_to_vitalFragment)
}
}
lmnb_medical_test_iv.setOnClickListener {
when (nestedNavController.currentDestination?.id) {
R.id.vitalFragment -> nestedNavController.navigate(R.id.action_vitalFragment_to_medicalTestFragment)
R.id.labResultFragment -> nestedNavController.navigate(R.id.action_labResultFragment_to_medicalTestFragment)
}
}
lmnb_lab_result_iv.setOnClickListener {
when (nestedNavController.currentDestination?.id) {
R.id.vitalFragment -> nestedNavController.navigate(R.id.action_vitalFragment_to_labResultFragment)
R.id.medicalTestFragment -> nestedNavController.navigate(R.id.action_medicalTestFragment_to_labResultFragment)
}
}
}
}
Этот метод работает, но он выглядит неоптимально, так как я должен вручную обрабатывать каждый случай. У нас на самом деле есть около 10+ пунктов в меню, так что много работы. Это как навигационная библиотека обрабатывает навигационный ящик? Есть ли другой способ справиться с этим более элегантно?