Как получить текущий фрагмент в ViewPager2

Я использовал эту зависимость ViewPager2:

реализация 'androidx.viewpager2: viewpager2: 1.0.0'

затем я написал код и сделал адаптер для FragmentStateAdapter, как показано ниже:

private inner class ViewPagerAdapter(fragmentManager: FragmentManager,
                                         lifecycle: Lifecycle, config: TribunConfig?)
        : FragmentStateAdapter(fragmentManager, lifecycle) {
        private val config: TribunConfig?
        override fun createFragment(position: Int): Fragment {
            return TribunNewsFragment.newInstance(if (menuTribun!!.get(position) == "News") "home"
            else menuTribun!!.get(position)!!.replace(" ", "").toLowerCase(), config)!!
        }

        override fun getItemCount(): Int {
            return menuTribun!!.size
        }

        init {
            this.config = config
        }
    }

в методе onCreate я реализую некоторый связанный с кодом viewpager2 и его адаптер, как показано ниже:

        viewPager2!!.offscreenPageLimit = 1
        viewPager2!!.adapter = ViewPagerAdapter(supportFragmentManager, lifecycle, config)
        TabLayoutMediator(tabLayout!!, viewPager2!!, TabLayoutMediator.TabConfigurationStrategy { tab: TabLayout.Tab?, position: Int -> tab!!.text = menuTribun!!.get(position) }).attach()

Но у меня проблема, когда я хочу сделать swipeRefresh. Моему swipeRefresh нужен текущий фрагмент для доступа к методу внутри фрагмента. Но в FragmentStateAdapter нет НИКАКИХ МЕТОДОВ getItem. Кто-нибудь может мне помочь?


person Nanda Z    schedule 08.04.2020    source источник
comment
1. Создайте свойство в своем адаптере для сохранения всех ваших фрагментов 2. Сохраните текущую позицию 3. Получите фрагмент из списка фрагментов (свойство) по позиции, когда вам это нужно.   -  person Oleg Skidan    schedule 08.04.2020
comment
не могли бы вы показать в коде, пожалуйста. так что я могу проголосовать за ваш ответ, если он правильный   -  person Nanda Z    schedule 08.04.2020
comment
Вы знакомы с EventBus?   -  person dariush f    schedule 08.04.2020
comment
@dariushf нет, еще нет   -  person Nanda Z    schedule 08.04.2020
comment
@NandaZ: Пожалуйста, покажите свой код, как вы добавляете фрагмент в пейджер   -  person Shweta Chauhan    schedule 08.04.2020
comment
@ShwetaChauhan, ты имел в виду, что хочешь увидеть класс TribunNewsFragment? если вы хотите знать, как я добавил фрагмент, я написал его в методе createFragment   -  person Nanda Z    schedule 08.04.2020


Ответы (2)


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

Что-то вроде этого:

    val fragments: MutableList<Fragment> = mutableListOf()

    private val config: TribunConfig?
    override fun createFragment(position: Int): Fragment {
        val fragment = TribunNewsFragment.newInstance(if (menuTribun!!.get(position) == "News") "home"
        else menuTribun!!.get(position)!!.replace(" ", "").toLowerCase(), config)!!

        fragments.add(fragment)
        return fragment
    }

Родитель:

 yourTabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
        override fun onTabSelected(tab: TabLayout.Tab?) {
            val fragment = adapter.fragments[tab!!.position]
            // cast fragment to your fragment class and do what you want
        }

        override fun onTabUnselected(tab: TabLayout.Tab?) {
        }

        override fun onTabReselected(tab: TabLayout.Tab?) {
        }
    })

Также вы можете использовать when или if-else для позиции ваших фрагментов или создать базовый класс с нужными вам методами и применить к нему получение фрагмента.

person Oleg Skidan    schedule 08.04.2020
comment
В качестве примечания ViewPager2 имеет обратный вызов измененной страницы developer.android.com/reference / androidx / viewpager2 / widget /, чтобы это можно было сделать без вкладок - person Andrew; 08.04.2020
comment
Но у меня была встречная проблема. Когда я пытаюсь щелкнуть вкладку, индекс которой превышает размер mutableList, и это вызывает сбой - person Nanda Z; 08.04.2020
comment
Как это возможно? У вас вкладок больше, чем фрагментов? - person Oleg Skidan; 08.04.2020
comment
это из-за viewPager2!!.offscreenPageLimit = 1, поэтому я не создаю весь фрагмент только два фрагмента для первого открытия - person Nanda Z; 08.04.2020
comment
Так что это просто. CurrentTab.position + 1 для вас максимум, кроме lastPosition. - person Oleg Skidan; 08.04.2020
comment
Думаю, я могу принять ваш ответ, потому что добавляю время задержки для события в onTabSelected. Это работает сейчас - person Nanda Z; 08.04.2020
comment
Это не обрабатывает изменения конфигурации (то есть приложение, у которого не хватает памяти в фоновом режиме) - createFragment не вызывается, когда это происходит, он восстанавливается без вызова этого, и ваш список становится пустым. - person lawonga; 14.05.2020
comment
@Iawonga прав. Вам необходимо сохранить фрагменты в FragmentManager и получить их после изменения конфигурации с помощью putFragment и getFragment соответственно. Очевидно, что это много шаблонов, и я думаю, что более формальный ответ - по возможности не полагаться на ссылки на фрагменты в своей деятельности. Я еще не видел хорошего примера от Google о том, как с этим справиться. - person rosghub; 29.08.2020
comment
Альтернативой может быть этот ответ, основанный на внутренней логике ViewPager2 хранения фрагментов по тегам. - person rosghub; 29.08.2020

Следуя ответу @Oleg, вы можете получить доступ к таким фрагментам в своем адаптере вместо создания локального списка и добавления каждого фрагмента в метод createFragment:

private val fragmentList: List<TribunNewsFragment>
        get() {
            return fragment.childFragmentManager.fragments.filterIsInstance<TribunNewsFragment>()
        }

Важно использовать childFragmentManager вместо fragmentManager, если вы создаете ViewPager внутри другого фрагмента.

И он переживает изменения конфигурации, что касается комментария @ lawonga по теме ответа.

person Rafael Guimarães    schedule 06.08.2020
comment
Похоже, у вас уже есть fragment ссылка. Как вы на него ссылаетесь со своего адаптера? - person rosghub; 23.08.2020