如何使用 Viewpager2 和 Mediator Tab Layout 动态添加和删除片段页面 [英] How do I dynamically add and remove fragment pages using Viewpager2 and Mediator Tab Layout

查看:55
本文介绍了如何使用 Viewpager2 和 Mediator Tab Layout 动态添加和删除片段页面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要根据服务器配置文件在运行时将片段添加到 viewpager2 以及选项卡.我见过的大多数 viewpager2 资源都使用新的 TabMediator Tab 布局展示了静态 viewpager2.我正在跳过 viewpager,因为我需要添加 viewpager2 支持的 RTL 和垂直滚动.

I need to add fragments to viewpager2 as well as tabs at runtime depending on server config file. Most viewpager2 resources I have seen showcase a static viewpager2 using the new TabMediator Tab layout. I am skipping viewpager as I need to add RTL and vertical scrolling supported by viewpager2.

我最关心的是如何在添加和删除片段时跟踪特定页面/片段的索引.已阅读教程和代码作为示例.

My biggest concern is how to I track the index of a specific page/fragment when I add and remove fragments. Have gone through this tutorial and code as an exapmple.

推荐答案

这就是你在 Kotlin 中实现它的方式

This is how you implement it in Kotlin

viewPager = binding.viewPagerContainer
        val tabLayout : TabLayout = binding.tabLayout

        val fragmentList : MutableList<Pair<String, Fragment>> = mutableListOf()
        fragmentList.add(Pair(getString(R.string.assets), AssetFragment.newInstance()))
        fragmentList.add(Pair(getString(R.string.news), NewsFragment.newInstance()))

        val adapter = AppFragmentAdapter(fragmentList, this)

        Handler(Looper.myLooper()!!).postDelayed({
            adapter.addFragment(Pair(getString(R.string.videos), VideosFragment.newInstance()))
        }, 1000)

        Handler(Looper.myLooper()!!).postDelayed({
            adapter.removeFragment(2)
        }, 2000)

        viewPager.adapter = adapter
        viewPager.offscreenPageLimit = 2

        val layoutInflater : LayoutInflater = LayoutInflater.from(context)

        viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {

            override fun onPageSelected(position: Int) {
                super.onPageSelected(position)
                val actionBar : ActionBar = (requireActivity() as AppCompatActivity).supportActionBar!!
                actionBar.title = adapter.getFragmentName(position)
            }

        })

        TabLayoutMediator(tabLayout, viewPager){ tab, position ->
            tab.customView = prepareTabView(layoutInflater, tabLayout, adapter.getFragmentName(position), tabIcons[position])
        }.attach()

在这里,我们已经测试过在启动活动或父片段时使用一些基本延迟添加和删除最后一个片段.您可以为每个选项卡创建自定义视图或仅使用 tab.text = "Tab Name";为简单起见.

Here we already tested to add and remove the last fragment using some basic delay upon launching an Activity or Parent Fragment. You can create a custom view for each tab or just use tab.text = "Tab Name" for simplicity.

现在您将与 ViewPager2 一起使用的适配器类型是 FragmentStateAdapter

Now the type of adapter you will be using with ViewPager2 for Fragment is FragmentStateAdapter

class AppFragmentAdapter(private val fragmentList: MutableList<Pair<String, Fragment>>, fragment: Fragment) : FragmentStateAdapter(fragment) {

//    private var pageIds = fragmentList.map { fragmentList.hashCode().toLong() }

    override fun getItemCount(): Int = fragmentList.size

    override fun createFragment(position: Int): Fragment {
        return fragmentList[position].second
    }

//    override fun getItemId(position: Int): Long = pageIds[position] // Make sure notifyDataSetChanged() works

//    override fun containsItem(itemId: Long): Boolean = pageIds.contains(itemId)

    fun getFragmentName(position: Int) = fragmentList[position].first

    fun addFragment(fragment: Pair<String, Fragment>) {
        fragmentList.add(fragment)
        notifyDataSetChanged()
    }

    fun removeFragment(position: Int) {
        fragmentList.removeAt(position)
        notifyDataSetChanged()
    }

}

如果您的结构是父片段 >ViewPager2 >子片段上面的代码可以正常工作.

If your structure is Parent Fragment > ViewPager2 > Child Fragments the above code will work fine.

如果您的结构是 Activity >ViewPager2 >片段只是变化

If your structure is Activity > ViewPager2 > Fragments just change

class AppFragmentAdapter(private val fragmentList: MutableList<Pair<String, Fragment>>, fragment: Fragment) : FragmentStateAdapter(fragment)

class AppFragmentAdapter(private val fragmentList: MutableList<Pair<String, Fragment>>, fragment: FragmentActivity) : FragmentStateAdapter(fragment)

然后代替

val adapter = AppFragmentAdapter(fragmentList, this)

像这样传递片段的活动

val adapter = AppFragmentAdapter(fragmentList, requireActivity())

从我们的适配器内部 FragmentStateAdapter(fragment) 已经处理了应该使用的 FragmentManager.

Internally FragmentStateAdapter(fragment) from our adapter already handle which FragmentManager is supposedly use.

活动 >ViewPager2 >片段

Activity > ViewPager2 > Fragments

public FragmentStateAdapter(@NonNull FragmentActivity fragmentActivity) {
    this(fragmentActivity.getSupportFragmentManager(), fragmentActivity.getLifecycle());
}

父片段>ViewPager2 >子片段

Parent Fragment > ViewPager2 > Child Fragments

public FragmentStateAdapter(@NonNull Fragment fragment) {
    this(fragment.getChildFragmentManager(), fragment.getLifecycle());
}

我被欺骗,首先在 SO 中搜索有关使用 ViewPager2 动态添加/删除 Fragment 的信息,然后再尝试我能用的最简单的方法上来.

I was deceived first by searching in SO about dynamically add/remove Fragment with ViewPager2 before trying the simplest approach I could come up.

这篇关于如何使用 Viewpager2 和 Mediator Tab Layout 动态添加和删除片段页面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆