#android #kotlin #navigation #fragment-backstack
#Android #kotlin #навигация #фрагмент-фоновый пакет
Вопрос:
Я еще раз прошу вашей интеллектуальной поддержки.
У меня есть фрагмент, который помещает несколько своих копий в фоновый пакет навигации следующим образом:
Navigation.findNavController(button).navigate(
TaskCollectFragmentDirections.actionTaskCollectFragmentSelf(args.taskIndex, args.screenIndex 1)
)
Приведенный выше код работает так, как задумано.
Проблема возникает, когда я хочу удалить указанное количество этих фрагментов из фонового пакета навигации. (Запускается нажатием кнопки.)
Я пытался сделать это так:
Navigation.findNavController(button).popBackStack(lastRecurringFragmentId, false)
Мой код компилируется и запускается, но просто ничего не делает. Когда я не даю никаких параметров popBackStack
функции, она правильно выскакивает из самого верхнего фрагмента. Я также могу использовать стрелку назад, чтобы вернуться к исходному фрагменту.
Если это имеет какое-либо значение, lastRecurringFragmentId
это происходит из этой функции:
fun getLastRecurringFragmentId(recurringFragmentCount: Int): Int {
val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment)!!
val backStackEntryCount = navHostFragment.childFragmentManager.backStackEntryCount
val indexOfRequested = backStackEntryCount - recurringFragmentCount
val requestedEntry = navHostFragment.childFragmentManager.getBackStackEntryAt(indexOfRequested)
return requestedEntry.id
}
График навигации выглядит следующим образом. Предполагается, что их должно быть несколько TaskCollectFragment
, и, наконец, один TaskEndFragment
в верхней части фонового пакета. Я хочу удалить некоторые TaskCollectFragment
элементы из стека, когда пользователь нажимает кнопку на TaskEndFragment
:
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@ id/mobile_navigation"
app:startDestination="@id/nav_home">
<fragment
android:id="@ id/nav_home"
android:name="ui.home.HomeFragment"
android:label="@string/menu_home"
tools:layout="@layout/fragment_home" >
<action
android:id="@ id/action_nav_home_to_taskCollectFragment"
app:destination="@id/taskCollectFragment" />
</fragment>
<fragment
android:id="@ id/taskCollectFragment"
android:label="TaskCollectFragment"
tools:layout="@layout/task_collect_fragment"
>
<action
android:id="@ id/action_taskCollectFragment_to_taskEndFragment"
app:destination="@id/taskEndFragment" />
<action
android:id="@ id/action_taskCollectFragment_self"
app:destination="@id/taskCollectFragment" />
<argument
android:name="taskIndex"
app:argType="integer" />
<argument
android:name="screenIndex"
app:argType="integer" />
</fragment>
<fragment
android:id="@ id/taskEndFragment"
android:name="ui.task.TaskEndFragment"
android:label="TaskEndFragment"
tools:layout="@layout/task_end_fragment">
<argument
android:name="taskIndex"
app:argType="integer" />
</fragment>
</navigation>
Есть ли способ, которым я могу извлекать фрагменты из фонового пакета, пока не будет выполнено определенное условие?
Комментарии:
1. Ваш
getLastRecurringFragmentId()
не имеет никакого смысла при использовании навигации — идентификаторы, которые вы передаетеpopBackStack()
, — этоandroid:id
s в вашем навигационном графике. Можете ли вы включить свой навигационный график?2. @ianhanniballake Означает ли это, что я не могу различать несколько экземпляров фрагмента?
3. Может быть, было бы лучше, если бы вы сказали, каким должен быть ваш стек после pop? Вы хотите, чтобы все ваши экземпляры
taskCollectFragment
были извлечены, и только теnav_home
, которые все еще находятся в стеке?4. @ianhanniballake Как я уже сказал, я хочу добавить некоторые из
taskCollectFragment
них. Может быть, всего несколько, может быть, все, это зависит от обстоятельств. Спасибо, что сообщили мне об источнике идентификаторов, это дало мне идею!
Ответ №1:
Я создал два почти идентичных фрагмента forSessionTaskCollectFragment
и recurringTaskCollectFragment
с той же ViewModel. Они выглядят одинаково, и с точки зрения пользователя они делают то же самое. forSessionTaskCollectFragment
s — это те, которые я хочу сохранить, а recurringTaskCollectFragment
s — это те, которые я хочу вернуть позже.
Из домашнего фрагмента мой навигационный график переходит в forSessionTaskCollectFragment
, оттуда он возвращается к себе или переходит к recurringTaskCollectFragment
, который также возвращается к себе или, наконец, переходит к TaskEndFragment
<fragment
android:id="@ id/nav_home"
android:name="ui.home.HomeFragment"
android:label="@string/menu_home"
tools:layout="@layout/fragment_home" >
<action
android:id="@ id/action_nav_home_to_orSessionTaskCollectFragment"
app:destination="@id/forSessionTaskCollectFragment" />
</fragment>
<fragment
android:id="@ id/forSessionTaskCollectFragment"
android:name="ui.task.ForSessionTaskCollectFragment"
android:label="ForSessionTaskCollectFragment" >
<action
android:id="@ id/action_forSessionTaskCollectFragment_self"
app:destination="@id/forSessionTaskCollectFragment" />
<action
android:id="@ id/action_forSessionTaskCollectFragment_to_recurringTaskCollectFragment"
app:destination="@id/recurringTaskCollectFragment" />
<argument
android:name="taskIndex"
app:argType="integer" />
<argument
android:name="screenIndex"
app:argType="integer" />
</fragment>
<fragment
android:id="@ id/recurringTaskCollectFragment"
android:name="ui.task.RecurringTaskCollectFragment"
android:label="TaskCollectFragment"
tools:layout="@layout/recurring_task_collect_fragment"
>
<action
android:id="@ id/action_recurringTaskCollectFragment_to_taskEndFragment"
app:destination="@id/taskEndFragment" />
<action
android:id="@ id/action_recurringTaskCollectFragment_self"
app:destination="@id/recurringTaskCollectFragment" />
<argument
android:name="taskIndex"
app:argType="integer" />
<argument
android:name="screenIndex"
app:argType="integer" />
</fragment>
Я помещаю forSessionTaskCollectFragment
s в стек, пока не дойду до точки, к которой хочу вернуться.
Navigation.findNavController(button).navigate(
if(args.screenIndex < viewModel.forSessionScreenCount) {
ForSessionTaskCollectFragmentDirections.actionForSessionTaskCollectFragmentSelf(args.taskIndex, args.screenIndex 1)
} else {
ForSessionTaskCollectFragmentDirections.actionForSessionTaskCollectFragmentToRecurringTaskCollectFragment(args.taskIndex, args.screenIndex 1)
}
)
После этого я помещаю фрагменты, которые позже захочу вставить обратно, и, наконец, перехожу к тому TaskEndFragment
месту, откуда я хочу вставить нужные фрагменты:
Navigation.findNavController(button).navigate(
if(args.screenIndex < viewModel.screenCount - 2) {
RecurringTaskCollectFragmentDirections.actionRecurringTaskCollectFragmentSelf(args.taskIndex, args.screenIndex 1)
} else {
RecurringTaskCollectFragmentDirections.actionRecurringTaskCollectFragmentToTaskEndFragment(args.taskIndex)
}
)
Итак, при нажатии кнопки TaskEndFragment
«s» я могу вернуться к точному месту в фоновом стеке, которое я пометил переходом с фрагментов «сеанса» на «повторяющиеся» фрагменты:
Navigation.findNavController(button).popBackStack(R.id.forSessionTaskCollectFragment, false)
Это было много хлопот, я не нашел ни одного примера для того, что я хотел сделать, но, наконец, удалось найти рабочее решение. Ianhanniballake еще раз спасибо, вы вызвали мою идею.
Комментарии:
1. Привет, o /. Это не ответ на вопрос, который вы задали. Вместо того, чтобы фактически вернуться к определенному фрагменту, вы перемещаетесь вперед.
2. Есть какие-либо объяснения? Все работает так, как ожидалось. Я предлагаю вам внимательно прочитать все это. Я перемещаюсь вперед, пока добавляю фрагменты. Хитрость заключается в том, чтобы изменить тип фрагмента, который я добавляю в тот момент, когда я хочу вернуться. Затем, когда мне нужно вернуться, я могу сделать это, вызвав «Navigation.findNavController(button).popBackStack(R.id.forSessionTaskCollectFragment, false)» Я почти уверен, что я не продвигаюсь вперед, делая это.