Android Компонент навигации - пользовательское меню с вложенным фрагментом NavHostFragment. Оптимально ли вручную определять каждое отдельное действие? - PullRequest
0 голосов
/ 26 марта 2020

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 справа для обработки навигации по всем дочерним фрагментам. Все они размещены в одном действии.

enter image description here

enter image description here

Это макет для 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+ пунктов в меню, так что много работы. Это как навигационная библиотека обрабатывает навигационный ящик? Есть ли другой способ справиться с этим более элегантно?

...