Удалите фрагмент specefi c из backstack, который не находится сверху backstack - PullRequest
0 голосов
/ 18 января 2020

Короткая версия:

У меня есть 5 фрагментов, добавленных в контейнер методом replace (A -> B -> C -> D -> E), теперь я хочу удалить 3-й фрагмент из моего backStack (C) и остаться на текущей странице, как это сделать?

Проблема:

У меня есть 3 фрагмента, FragmentA, FragmentB и FragmentC, и пользователь перемещается из A to B then C. Во фрагменте C, когда пользователь выполняет действие (я называю это ActionX), мне нужно удалить FragmentB из моего менеджера фрагментов BackStack (пока пользователь все еще находится во фрагменте C), и я не хочу, чтобы пользователь чтобы заметить что-то, просто когда он нажимает на телефон, показывает другой фрагмент (так что если ActionX произошло, когда пользователь нажал на кнопку «Фрагмент А», если не показывает «Фрагмент Б»)

Вот как я показываю свой fragments (я устанавливаю фрагмент имя для имени и тег, чтобы найти их, когда мне нужно)

public void showFragment(Fragment fragment) {
        FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
        String tag = fragment.getClass().getSimpleName();
        fragmentTransaction.replace(R.id.fragment_container, fragment, tag);
        fragmentTransaction.addToBackStack(tag);
        fragmentTransaction.commit();
}

Я пробовал решения, упомянутые в некоторых потоках SO (например, this ), но они работают только с верхним фрагментом в стеке или они предложить не FragmentB (что я не могу, потому что я не знаю, что будет делать пользователь), также поиск и удаление FragmentB из стека не работает. Одно из решений состоит в том, чтобы переопределить onBackPressed моей Деятельности и проверить, произошел ли ActionX, и дважды выдвинуть мой backStack.

, что я пытался:

  1. это не работает (фрагментBInStack не равен нулю, но когда Убираю это ничего не происходит)
val fragmentBInStack = manager.findFragmentByTag(FragmentB::class.java.simpleName)
fragmentBInStack?.let {
    manager.beginTransaction().remove(it).commit()
}
этот код удаляет как Фрагмент C, так и ФрагментB и показывает FragmentA (я хочу остаться во Фрагменте C), если я использую 0 вместо POP_BACK_STACK_INCLUSIVE, он отображает только Фрагмент C и показывает FragmentB
manager.popBackStack(FragmentB::class.java.simpleName, FragmentManager.POP_BACK_STACK_INCLUSIVE)

это пример кода того, что я хочу сделать

class FragmentC : Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        view.findViewById<View>(R.id.action_x).setOnClickListener {

            //here I want to remove FragmentB from back Stack and stay in FragmentC, just later when user presses back I want to show FragmentA
            val manager = activity!!.supportFragmentManager
            val fragmentBInStack = manager.findFragmentByTag(FragmentB::class.java.simpleName)
            fragmentBInStack?.let {
                manager.beginTransaction().remove(it).commit()
            }
        }
    }

Ответы [ 2 ]

0 голосов
/ 18 января 2020

Я могу предложить следующий подход: использовать тот же экземпляр ViewModel (используйте ViewModelProvider действия для создания экземпляра модели представления) с событием ActionX LiveData в FragmentB и FragmentC. В FragmentC устанавливается значение LiveData, а FragmentB наблюдает за изменениями данных в реальном времени.

Вот исходный код.

1. посмотреть модель

class InterFragmentViewModel : ViewModel() {
    val actionXLiveData = MutableLiveData<Boolean>()
}

2. Фрагмент C

class FragmentC : AppCompatDialogFragment() {

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        view.findViewById<View>(R.id.action_x).setOnClickListener {
            ViewModelProvider(requireActivity()).get(InterFragmentViewModel::class.java)
                .actionXLiveData.value = true
        }
    }
}

3. Фрагмент B

class FragmentB : AppCompatDialogFragment() {

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        ViewModelProvider(requireActivity()).get(InterFragmentViewModel::class.java)
            .actionXLiveData.observe(viewLifecycleOwner, Observer {
            parentFragmentManager.popBackStack()
        })

    }
}
0 голосов
/ 18 января 2020

Хорошо, во-первых, вы должны добавить свои фрагменты в отдельной транзакции и изменить replace на add

supportFragmentManager
    .beginTransaction()
    .add(R.id.fragment_container, fragment2, tag2)
    .addToBackStack(tag2)
    .commit()

Затем вы удалите фрагмент, как вы делаете:

val fragment2 = supportFragmentManager.findFragmentByTag(tag2)!!
supportFragmentManager.beginTransaction().remove(fragment2).commit()

Последний шаг - просто popBackStack:

supportFragmentManager.popBackStack()
...