Есть ли способ сохранить фрагмент живым при использовании BottomNavigationView с новым NavController? - PullRequest
0 голосов
/ 23 мая 2018

Я пытаюсь использовать новый компонент навигации.Я использую BottomNavigationView с navController: NavigationUI.setupWithNavController (bottomNavigation, navController)

Но когда я переключаю фрагменты, они каждый раз уничтожают / создают, даже если они ранее использовались.

Есть ли способ сохранить ссылку на наши основные фрагменты в BottomNavigationView?

Ответы [ 6 ]

0 голосов
/ 29 июля 2019

Мне помогло решение, предоставленное @ piotr-prus, но мне пришлось добавить некоторую текущую проверку пункта назначения:

if (navController.currentDestination?.id == resId) {
    return       //do not navigate
}

без этой проверки текущий пункт назначения будет воссоздан, если вы по ошибке перейдете к нему, потому чтоон не найден в заднем стеке.

0 голосов
/ 27 апреля 2019

Я использовал ссылку, предоставленную @STAR_ZERO, и она отлично работает.Для тех, у кого проблема с кнопкой «Назад», вы можете обработать ее на хосте активности / навигации следующим образом.

override fun onBackPressed() {
        if(navController.currentDestination!!.id!=R.id.homeFragment){
            navController.navigate(R.id.homeFragment)
        }else{
            super.onBackPressed()
        }
    }

Просто проверьте, является ли текущий пункт назначения вашим корневым / домашним фрагментом (обычно первым в нижней части).представление навигации), если нет, просто вернитесь к фрагменту, если да, выйдите из приложения или сделайте все, что вы хотите.

Кстати, это решение должно работать вместе со ссылкой на решение, предоставленной STAR_ZERO выше,используя keep_state_fragment .

0 голосов
/ 29 марта 2019

После многих часов исследований я нашел решение.Это было все время прямо перед нами :) Есть функция: popBackStack(destination, inclusive), которая перемещается к данному месту назначения, если найдена в backStack.Возвращает логическое значение, поэтому мы можем перейти туда вручную, если контроллер не найдет фрагмент.

if(findNavController().popBackStack(R.id.settingsFragment, false)) {
        Log.d(TAG, "SettingsFragment found in backStack")
    } else {
        Log.d(TAG, "SettingsFragment not found in backStack, navigate manually")
        findNavController().navigate(R.id.settingsFragment)
    }
0 голосов
/ 22 марта 2019

Ссылка на образцы Google Просто скопируйте NavigationExtensions в ваше приложение и настройте его в качестве примера.Прекрасно работает.

0 голосов
/ 20 сентября 2018

На данный момент недоступно.

В качестве обходного пути вы можете сохранить все свои извлеченные данные в модели представления и иметь эти данные легкодоступными при воссоздании фрагмента.Убедитесь, что вы получаете представление с использованием контекста действий.

Вы можете использовать LiveData, чтобы сделать ваши данные доступными для наблюдения с учетом жизненного цикла

0 голосов
/ 04 августа 2018

Попробуйте это.

Навигатор

Создание настраиваемого навигатора.

@Navigator.Name("custom_fragment")  // Use as custom tag at navigation.xml
class CustomNavigator(
    private val context: Context,
    private val manager: FragmentManager,
    private val containerId: Int
) : FragmentNavigator(context, manager, containerId) {

    override fun navigate(destination: Destination, args: Bundle?, navOptions: NavOptions?) {
        val tag = destination.id.toString()
        val transaction = manager.beginTransaction()

        val currentFragment = manager.primaryNavigationFragment
        if (currentFragment != null) {
            transaction.detach(currentFragment)
        }

        var fragment = manager.findFragmentByTag(tag)
        if (fragment == null) {
            fragment = destination.createFragment(args)
            transaction.add(containerId, fragment, tag)
        } else {
            transaction.attach(fragment)
        }

        transaction.setPrimaryNavigationFragment(fragment)
        transaction.setReorderingAllowed(true)
        transaction.commit()

        dispatchOnNavigatorNavigated(destination.id, BACK_STACK_DESTINATION_ADDED)
    }
}

NavHostFragment

Создание настраиваемого NavHostFragment.

class CustomNavHostFragment: NavHostFragment() {
    override fun createFragmentNavigator(): Navigator<out FragmentNavigator.Destination> {
        return CustomNavigator(requireContext(), childFragmentManager, id)
    }
}

navigation.xml

Использовать пользовательский тег вместо тега фрагмента.

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/navigation"
    app:startDestination="@id/navigation_first">

    <custom_fragment
        android:id="@+id/navigation_first"
        android:name="com.example.sample.FirstFragment"
        android:label="FirstFragment" />
    <custom_fragment
        android:id="@+id/navigation_second"
        android:name="com.example.sample.SecondFragment"
        android:label="SecondFragment" />
</navigation>

макет активности

Использовать CustomNavHostFragment вместо NavHostFragment.

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment
        android:id="@+id/nav_host_fragment"
        android:name="com.example.sample.CustomNavHostFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/bottom_navigation"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/navigation" />

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_navigation"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:menu="@menu/navigation" />

</androidx.constraintlayout.widget.ConstraintLayout>

Обновление

Я создал пример проекта. ссылка

Я не создаю пользовательский NavHostFragment.Я использую navController.navigatorProvider += navigator.

...