Как программно изменить начальный пункт назначения навигационного графа [Jetpack] - PullRequest
0 голосов
/ 04 июля 2018

В основном у меня есть следующий график навигации:

enter image description here

Я хочу изменить свою начальную точку на навигационном графике на fragment 2 сразу после ее достижения (чтобы предотвратить возврат к fragment 1 при нажатии кнопки назад - как на заставке).

Это мой код:

navGraph = navController.getGraph();
navGraph.setStartDestination(R.id.fragment2);
navController.setGraph(navGraph);

Но, очевидно, он не работает и возвращается к fragment 1 после нажатия кнопки назад.

Я делаю это неправильно? Есть ли другое решение?

Ответы [ 2 ]

0 голосов
/ 27 октября 2018

Я нашел решение для этого, но это некрасиво. Я предполагаю, что этого следует ожидать с альфа-библиотекой, но я надеюсь, что Google пытается упростить / исправить это, поскольку это довольно популярный шаблон навигации.

Решение Алексея у меня не сработало. Моя проблема заключалась в том, что на панели действий отображаются стрелки вверх с помощью:

NavigationUI.setupActionBarWithNavController(this, navController)

Если бы я сделал так, как предлагает Алексей, у моего нового стартового фрагмента все еще была стрелка, указывающая на мой начальный стартовый фрагмент. Если бы я нажал эту стрелку вверх, мое приложение перезапустилось бы, перейдя к себе (новый начальный фрагмент)

Вот код, необходимый для того, чтобы получить то, что я хотел:

  • Фрагмент # 1, где мое приложение изначально запускается
  • Я могу выполнить проверку подлинности во фрагменте № 1, а затем программно изменить начало фрагмента № 2.
  • Однажды во Фрагменте # 2 стрелка вверх не появляется, и нажатие кнопки «Назад» не приведет вас к Фрагменту № 1.

Вот код, который выполняет это. В моей деятельности по созданию:

// Setup the toolbar
val toolbar = findViewById<Toolbar>(R.id.toolbar)
setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(false)

// Configure the navigation
val navHost = nav_host_fragment as NavHostFragment
graph = navHost.navController
        .navInflater.inflate(R.navigation.nav_graph)
graph.startDestination = R.id.welcomeFragment

// This seems to be a magical command. Not sure why it's needed :(
navHost.navController.graph = graph

NavigationUI.setupActionBarWithNavController(this, navHost.navController)

а также:

fun makeHomeStart(){
    graph.startDestination = R.id.homeFragment
}

Затем во фрагменте № 1 onActivityCreated, согласно предложению Алексея:

override fun onActivityCreated(savedInstanceState: Bundle?) {
    ...

    // Check for user authentication
    if(sharedViewModel.isUserAuthenticated()) {

        (activity as MainActivity).makeHomeStart() //<---- THIS is the key
        val navOptions = NavOptions.Builder()
                .setPopUpTo(R.id.welcomeFragment, true)
                .build()
        navController.navigate(R.id.action_welcomeFragment_to_homeFragment,null,navOptions)

    } else {
        navController.navigate(R.id.action_welcomeFragment_to_loginFragment)
    }
}

Код ключа: (activity as MainActivity).makeHomeStart(), который просто запускает метод в действии, который изменяет графики startDestination. Я мог бы очистить это и превратить в интерфейс, но я буду ждать Google и надеюсь, что они улучшат весь этот процесс. Метод setPopUpTo кажется мне плохо названным, и не интуитивно понятно, что вы называете фрагмент, который вырезан из графика. Мне также странно, что они вносят эти изменения в navOptions. Я думаю, что navOptions будет относиться только к действиям навигации, к которым они подключены.

И я даже не знаю, что делает navHost.navController.graph = graph, но без него стрелки вверх возвращаются. (

Я использую Navigation 1.0.0-alpha06.

0 голосов
/ 04 июля 2018

UPDATE:

Когда у вас есть навигационный график, такой:

<fragment
    android:id="@+id/firstFragment"
    android:name="com.appname.package.FirstFragment" >
    <action
        android:id="@+id/action_firstFragment_to_secondFragment"
        app:destination="@id/secondFragment" /> 
</fragment>

<fragment
    android:id="@+id/secondFragment"
    android:name="com.appname.package.SecondFragment"/>

И вы хотите перейти ко второму фрагменту и сделать его корнем вашего графика, укажите следующий NavOptions:

NavOptions navOptions = new NavOptions.Builder()
        .setPopUpTo(R.id.firstFragment, true)
        .build();

И использовать их для навигации:

Navigation.findNavController(view).navigate(R.id.action_firstFragment_to_secondFragment, bundle, navOptions);

setPopUpTo(int destinationId, boolean inclusive) - всплыть до заданного пункта назначения перед навигацией. При этом все несоответствующие пункты назначения извлекаются из заднего стека, пока этот пункт назначения не будет найден.

destinationId - пункт назначения для всплывающего окна, очищающий все промежуточные пункты назначения.

inclusive - true, чтобы извлекать заданное место назначения из заднего стека.


АЛЬТЕРНАТИВА:

<fragment
    android:id="@+id/firstFragment"
    android:name="com.appname.package.FirstFragment" >
<action
    android:id="@+id/action_firstFragment_to_secondFragment"
    app:destination="@id/secondFragment"
    app:popUpTo="@+id/firstFragment"
    app:popUpToInclusive="true" /> 
</fragment>

<fragment
    android:id="@+id/secondFragment"
    android:name="com.appname.package.SecondFragment"/>

А потом по вашему коду:

findNavController(fragment).navigate(
    FirstFragmentDirections.actionFirstFragmentToSecondFragment())

Старый ответ

Устаревший : Атрибут clearTask для действий и связанного API в NavOptions устарел.

Источник: https://developer.android.com/jetpack/docs/release-notes


Если вы хотите изменить свой корневой фрагмент на fragment 2 (например, после нажатия кнопки «Назад» на fragment 2 вы выйдете из приложения), вы должны поставить следующий атрибут в action или destination:

app:clearTask="true"

Практически это выглядит следующим образом:

<fragment
    android:id="@+id/firstFragment"
    android:name="com.appname.package.FirstFragment"
    android:label="fragment_first" >
    <action
        android:id="@+id/action_firstFragment_to_secondFragment"
        app:destination="@id/secondFragment"
        app:clearTask="true" /> 
</fragment>

<fragment
    android:id="@+id/secondFragment"
    android:name="com.appname.package.SecondFragment"
    android:label="fragment_second"/>

Я добавил app:clearTask="true" к действию.


Теперь при выполнении навигации от fragment 1 до fragment 2 используйте следующий код:

Navigation.findNavController(view)
        .navigate(R.id.action_firstFragment_to_secondFragment);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...