如何在ViewPager2中获取当前片段

4

我使用了ViewPager2依赖库:

implementation '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()

但是我在制作下拉刷新时遇到了问题。我的下拉刷新需要当前片段访问片段内部的方法。但是在FragmentStateAdapter中getItem没有方法。有人能帮助我吗?


  1. 在您的适配器中创建属性以保存所有片段
  2. 保存当前位置
  3. 当需要时,通过位置从片段列表(属性)获取片段
- Oleg Skidan
你能否用代码展示一下?这样我就可以投票给你的答案,如果它是正确的。 - Nanda Z
你熟悉EventBus吗? - Kapta
@dariushf 不,还没有。 - Nanda Z
@NandaZ:请展示一下你在ViewPager中添加Fragment的代码。 - Shweta Chauhan
@ShwetaChauhan 你是想看 TribunNewsFragment 类吗?如果你想知道我是如何添加片段的,我已经在方法 createFragment 中写了。 - Nanda Z
2个回答

3
  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?) {
        }
    })

您也可以使用 whenif-else 来确定片段的位置,或者创建一个包含所需方法的基类,并将获取的片段转换为它。


1
作为一个提示,ViewPager2有一个页面更改回调https://developer.android.com/reference/androidx/viewpager2/widget/ViewPager2.OnPageChangeCallback,因此可以在没有选项卡的情况下完成。 - Andrew
1
这是因为 viewPager2!!.offscreenPageLimit = 1,所以我只创建了两个片段来进行首次打开。 - Nanda Z
所以很简单。对于你来说,CurrentTab.position+1是最大值,除了lastPosition。 - Oleg Skidan
8
这个功能无法处理配置更改(例如应用在后台运行时内存不足)- 当发生这种情况时,createFragment 不会被调用,它会在不调用该函数的情况下进行还原,导致列表变为空。 - lawonga
这会导致在可变列表中维护的片段出现内存泄漏问题。 - Sagar Pujari
显示剩余5条评论

1

在@Oleg的答案之后,您可以像这样在适配器中访问片段,而不是创建本地列表并在createFragment方法中添加每个片段:

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

如果您在另一个片段中创建ViewPager,则使用childFragmentManager而不是fragmentManager非常重要。

关于@lawonga在答案主题中的评论,它可以经受住配置更改。


1
看起来你已经在这里有一个“fragment”引用了。你是如何从你的适配器中引用它的? - rosghub

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接