- Урок 26. Navigation. Параметры навигации
- destination Fragment
- Attributes
- Arguments
- Actions
- Deep links
- destination Activity
- Attributes
- Arguments
- Deep links
- Action
- Атрибуты
- Transitions
- Argument Default Values
- Pop Behaviour
- Launch Options
- NavOptions
- Как очистить стек навигации после перехода к другому фрагменту в Android
- Get started with the Navigation component
- Set up your environment
- Groovy
- Kotlin
- Create a navigation graph
- Navigation Editor
- Navigate Back with Navigation Component
- Or how to do that without creating a new instance of Fragment
- The problem
- Understanding
- Solution
- Update at the end
Урок 26. Navigation. Параметры навигации
В этом уроке разбираемся, как задавать параметры при навигации.
Полный список уроков курса:
В графе у нас есть три основных объекта, у которых мы можем задавать параметры: это destination Fragment, destination Activity и action.
Рассмотрим каждый из них подробно.
destination Fragment
Attributes
Type — это тип destination, в данном случае Fragment.
Label — текстовое описание. Его можно получить в коде.
Также оно будет использовано в случае интеграции с Navigation Drawer. Об этом будет следующий урок.
В качестве значения вы можете указать строковый ресурс, например: @string/fragment3_label
ID — уже знакомый нам атрибут, используется в методе navigate для навигации к этому destination. ID генерируется автоматически, но всегда можно ввести свое более осмысленное значение.
Class — класс фрагмента.
Set Start Destination — этой кнопкой можно destination сделать стартовым. Он будет отображаться первым при запуске.
Arguments
Возможность задать аргументы с значениями по умолчанию. Это мы подробно рассмотрели в прошлом уроке.
Actions
Список action, выходящих из этого destination. На скриншоте выше только один action, который ведет в SecondActivity. Но их может быть несколько.
Deep links
Об этом поговорим в отдельном уроке.
destination Activity
Attributes
Type, Label, ID, Class — аналогичны атрибутам destination Fragment.
Action и Data — соответствуют стандартным полям action и data в Intent классе. Заполняете их здесь и в Activity достаете из getIntent().getAction() и getIntent().getData().
Pattern — это примерно то же, что и Data, но с параметрами. Т.е. вы здесь задаете свой Uri и в нем указываете имена параметров в фигурных скобках.
На скриншоте выше я указал Uri: content://media/photo/
У него два параметра folder и id. От нас потребуется при вызове Activity передать значения для этих параметров через Bundle.
Параметры должны быть строковые.
В результате в Activity метод getIntent().getData() вернет нам: content://media/photo/camera/100.jpg
Arguments
Аналогичны аргументам destination Fragment.
Deep links
Об этом поговорим в отдельном уроке.
Обратите внимание, что нет списка Actions. Потому что граф действует только в пределах своего Activity. Переход в другое Activity — это уход из этого графа и дальнейшие перемещения будут определяться уже другим графом.
И нет кнопки Set Start Destination. Выходная из графа точка не может быть стартовой.
Action
Напомню, что action — это возможность указать дополнительные параметры при вызове destination. Рассмотрим эти параметры.
Пример: action из Fragment2 в Fragment3
Атрибуты
C Type и ID все понятно.
Destination — показывает, куда ведет action. Т.е. какой destination будет открыт, если вызвать метод NavController.navigate с ID этого action.
Transitions
Возможность задать анимацию перехода между destination.
Этот action ведет с Fragment2 на Fragment3. Соответственно:
Enter — анимация для появления Fragment3
Exit — анимация для исчезания Fragment2.
А когда возвращаемся с Fragment3 на Fragment2, то
Pop Enter — анимация появления Fragment2
Pop Exit — анимация исчезанияFragment3
Под капотом эти анимации просто передаются в FragmentTransaction:
Argument Default Values
Аргументы берутся из destination, в который ведет action. Здесь можно задать им значения по умолчанию.
Pop Behaviour
Допустим у нас есть три destination.
Мы поочередно их открываем в Activity: fragment1 > fragment2 > fragment3.
По каким то причинам нам надо, чтобы при возврате назад из fragment3 мы сразу попадали в fragment1 (минуя fragment2). Для этого мы создаем action, который ведет из fragment2 в fragment3 и укажем ему Pop To = fragment1. Теперь при вызове этого action система сбросит backStack до указанного в Pop To фрагмента.
В результате при возврате из Fragment3 попадаем в Fragment1.
Если включен чекбокс Inclusive, то destination, указанный в Pop To также будет закрыт и мы попадем на destination, который был перед ним.
Launch Options
Эти параметры зависят от того, куда ведет action: в Activity или в фрагмент.
Рассмотрим сначала для случая, когда action ведет в Activity.
Single Top — добавляет в Intent вызова Activity флаг Intent.FLAG_ACTIVITY_SINGLE_TOP
Document — добавляет в Intent вызова Activity флаг Intent.FLAG_ACTIVITY_NEW_DOCUMENT
Clear Task — cбрасывает стэк текущего графа до стартового destination. Добавляет в Intent вызова Activity флаг Intent.FLAG_ACTIVITY_CLEAR_TASK. Не очень понятный режим. Возможно еще просто не доведен до ума.
Если же action ведет в фрагмент:
Single Top — если текущий фрагмент тот же, что и вызываемый, то вызов будет проигнорирован.
Document — похоже, что никак не используется.
Clear Task — стэк текущего графа очищается до стартового фрагмента. Транзакция перехода в новый фрагмент не добавляется в backStack. Соответственно, вызываемый фрагмент заменяет текущий и становится единственным.
NavOptions
Все выше рассмотренные параметры можно задавать программно в объекте NavOptions и далее передавать этот объект в метод navigate.
Источник
Как очистить стек навигации после перехода к другому фрагменту в Android
Я использую новый компонент архитектуры навигации в android, и я застрял в очистке стека навигации после перехода к новому фрагменту.
Пример: я нахожусь в loginFragment и хочу, чтобы этот фрагмент был очищен из стека, когда я перехожу к домашнему фрагменту, чтобы пользователь не возвращался обратно в loginFragment, когда он нажимает кнопку «Назад».
Я попытался использовать NavOptions в navigate () , но кнопка назад все еще отправляет меня обратно в loginFragment
Сначала добавьте атрибуты app:popUpTo=’your_nav_graph_id’ и app:popUpToInclusive=»true» в тег действия.
Во-вторых, перейдите к месту назначения, используя указанное выше действие в качестве параметра.
Дополнительную информацию см. В документации .
ПРИМЕЧАНИЕ . Если вы используете метод навигации navigate(@IdRes int resId) , вы не получите желаемого результата. Следовательно, я использовал метод navigate(@NonNull NavDirections directions) .
Я думаю, ваш вопрос конкретно касается того, как использовать Pop Behavior / Pop To / app: popUpTo (в xml)
В документации
всплывающее окно до указанного пункта назначения перед навигацией. Это выталкивает все несовпадающие места назначения из заднего стека, пока это место назначения не будет найдено.
Пример (простое приложение для поиска вакансий)
мой график start_screen_nav выглядит следующим образом:
если я хочу перейти EmployerMainFragment и вывести все, включая, startScreenFragment тогда код будет:
если я хочу перейти EmployerMainFragment и вывести все, исключая, startScreenFragment тогда код будет:
если я хочу перейти EmployerMainFragment и открыть, loginFragment но не startScreenFragment тогда, код будет:
В моем случае мне нужно было удалить все из заднего стека, прежде чем я открою новый фрагмент, поэтому я использовал этот код
первая строка удаляет задний стек, пока он не достигнет фрагмента, указанного в моем случае, это домашний фрагмент, поэтому он полностью удаляет весь задний стек, и когда пользователь щелкает обратно в fragment_company, он закрывает приложение.
ПРИМЕЧАНИЕ. Очистить задачу устарело, официальное описание
Этот метод устарел. Используйте setPopUpTo (int, boolean) с идентификатором графа NavController и установите для него значение true.
Старый ответ
Если вы не хотите пройти через весь этот пух в коде, вы можете просто проверить Clear Task в Launch Options в свойствах действия.
Изменить: начиная с Android Studio 3.2 Beta 5, очистить задачу больше не отображается в окне параметров запуска, но вы все равно можете использовать ее в XML-коде навигации, в теге действия , добавив
Источник
Get started with the Navigation component
This topic shows you how to set up and work with the Navigation component. For a high level overview of the Navigation component, see the Navigation overview.
Set up your environment
To include Navigation support in your project, add the following dependencies to your app’s build.gradle file:
Groovy
Kotlin
For information on adding other Architecture Components to your project, see Adding components to your project.
Create a navigation graph
Navigation occurs between your app’s destinations—that is, anywhere in your app to which users can navigate. These destinations are connected via actions.
A navigation graph is a resource file that contains all of your destinations and actions. The graph represents all of your app’s navigation paths.
Figure 1 shows a visual representation of a navigation graph for a sample app containing six destinations connected by five actions. Each destination is represented by a preview thumbnail, and connecting actions are represented by arrows that show how users can navigate from one destination to another.
Figure 1. A navigation graph that shows previews of six different destinations that are connected via five actions.
- Destinations are the different content areas in your app.
- Actions are logical connections between your destinations that represent paths that users can take.
To add a navigation graph to your project, do the following:
- In the Project window, right-click on the res directory and select New > Android Resource File. The New Resource File dialog appears.
- Type a name in the File name field, such as «nav_graph».
- Select Navigation from the Resource type drop-down list, and then click OK.
When you add your first navigation graph, Android Studio creates a navigation resource directory within the res directory. This directory contains your navigation graph resource file ( nav_graph.xml , for example).
Navigation Editor
After adding a graph, Android Studio opens the graph in the Navigation Editor. In the Navigation Editor, you can visually edit navigation graphs or directly edit the underlying XML.
Figure 2. The Navigation Editor
- Destinations panel: Lists your navigation host and all destinations currently in the Graph Editor.
- Graph Editor: Contains a visual representation of your navigation graph. You can switch between Design view and the underlying XML representation in the Text view.
- Attributes: Shows attributes for the currently-selected item in the navigation graph.
Click the Text tab to see the corresponding XML, which should look similar to the following snippet:
Источник
Navigate Back with Navigation Component
Or how to do that without creating a new instance of Fragment
Sep 27, 2019 · 4 min read
As we all know, Google introduced Navigation Components some time ago. And moreover there is already 2.1.0 version at the moment. But there is small problem: we can not go back to specific fragment without its recreation. So this small article will be about workaround, you can use to eliminate such flaw.
The problem
Suppose we have One Activity Several fragments n a vigation (by the way I wrote about such pattern previously, you can check that here). And suppose we have 3 fragments. Fragment one has its own state, which can be saved and restore, and fragment three contain a button to go back to the first one. You can check base project here(code) and here(xml).
To navigate from third fragment to first one we use navigation action with attribute popUpTo :
To understand the current problem we need to change state of first fragment to be different from default one, then go to the third fragment, and then press a button to navigate back to the first one and BAM, you loose you saved state and have default one again:
Moreover if we slow our open/close fragment animations you will see, that the animation of going back to first fragment is not really smooth:
Understanding
That happens because first fragment is getting deleted and recreate from scratch. Let’s go to source code of Navigation library to check that.
Actually all basic navigation work starts, when you call NavController.navigate . At this point 2 main steps happens (at least two main steps, that are important for us):
- Popup back stack until we reach fragment specified by popUpTo attribute
- Create new fragment, specified by destinationId attribute
Eventually we will come to FragmentNavigator.navigate method, which creates needed fragment inside. So actually without specifying popUpInclusive attribute we will have new instance of Fragment1 with old instance, lying in the back stack. With using this attribute, old fragment will be permanently deleted and replaced by new one.
Solution
Unfortunately I didn’t found any elegant solution:
- Y̶o̶u̶ ̶c̶a̶n̶ ̶n̶o̶t̶ ̶a̶v̶o̶i̶d̶ ̶w̶r̶i̶t̶i̶n̶g̶ ̶d̶e̶s̶t̶i̶n̶a̶t̶i̶o̶n̶I̶d̶,̶ ̶s̶i̶n̶c̶e̶ ̶t̶h̶i̶s̶ ̶a̶t̶t̶r̶i̶b̶u̶t̶e̶ ̶i̶s̶ ̶r̶e̶q̶u̶i̶r̶e̶d̶ . Actually this is not true. You can!! And this is actual right solution . Check the UPD in the end of article
- You can not use any other attributes
- You can not adjust FragmentNavigator for your needs
One thing you can do, that will help us, is to specify your own Navigator. So let’s do that.
First, describe you NavHostFragment:
Next, create your own Navigator, that will inherit fragment navigator. The main change here will be checking wether popUpTo is equal to destination . And if yes, that probably means (at least in our project) that you just want to go back to that fragment without recreation, so you can just return navDest without changing:
Don’t forget to place @Navigator.Name annotation on class with name fragment, so that your navigator will be used as FragmentNavigator instead of default one.
And the last thing override method of creating fragment navigator in NavHostFragment . And use that fragment instead of default one in your xml our whatever place.
Now lets check our flow with new awesome approach 😉
Update at the end
While I wrote that article, I’ve checked the source code of Navigation component one more time and realized, that I was completely blind 🙁
As appeared, you may not specify destination attribute, but specify popUpTo attribute. In that case NavController will know, that you want just to go back till fragment, specified in popUpTo attribute without creating anything else.
So the only one right solution in this problem, which I described at the beginning of the article, is:
So this whole article is becoming useless, but I just didn’t want to throw my little research away, considering the fact that I already wrote almost everything and I had no other material on that month. 🙁
Источник