ViewPager2动态添加删除Fragment

ViewPager2动态添加删除Fragment

需求

未登录显示 B,C 两个Tab
登录后显示 A,B,C三个Tab
其实不一定会是 ABC这个顺序,BAC,BCA,也是可能的
单纯的修改getItemCount()这个方法的返回值,比如未登录返回2,登录后返回3,然后调用viewPager.adapter!!.notifyDataSetChanged() 是不能保证Fragment正确显示的,如果正确显示了想必你们也不会搜到这篇博客了。
直接依靠position是无法做到我们的需求的,就拿未登录显示BC,登录后显示ABC这个需求来说
在未登录的时候position返回为 0,1,登录后返回为0,1,2。在createFragment这个方法中如何在position=0时未登录显示B,登录显示A;position=1时未登录显示C,登录显示B;position=2时登录显示C呢
我是这么做得,登录后和未登录对应着mIds[0,1,2],mIds1[1,2],这样登录的position0的id=0,未登录的position0的id=1。

 override fun createFragment(position: Int): Fragment {
        val id: Long
        if (DataRepo.isLogin()) {
            id = mIds[position] //[0,1,2]
        } else {
            id = mIds1[position]//[1,2]
        }
        when (id) {
            0L -> {
                //加载A
            }
            1L -> {
                //加载B
            }
            2L -> {
                //加载C
            }
        }
    }

但仅仅这样做还不够哦,因为你会发现Fragment还是没有正确显示,因为在FragmentStateAdapter中维护着一个稀疏数组LongSparseArray缓存已加载的Fragment,他通过getItemId(position)来作为索引获取Fragment,没有找到Framgent就会调用createFragment(position),这个getItemId默认返回position,这下明白了吧,我们未登录和已登录的Tab对应的position是不同的。

 private void ensureFragment(int position) {
        long itemId = getItemId(position);
        if (!mFragments.containsKey(itemId)) {
            // TODO(133419201): check if a Fragment provided here is a new Fragment
            Fragment newFragment = createFragment(position);
            newFragment.setInitialSavedState(mSavedStates.get(itemId));
            mFragments.put(itemId, newFragment);
        }
    }
    

所以还需要重写getItemId和containsItem两个方法

    override fun getItemId(position: Int): Long {
        if (DataRepo.isLogin()) {
            return mIds[position]
        } else {
            return mIds1[position]
        }
    }

    override fun containsItem(itemId: Long): Boolean {
        if (DataRepo.isLogin()) {
            return mIds.contains(itemId)
        } else {
            return mIds1.contains(itemId)
        }
    }

这样一来,未登录的时候position =0,系统调用ensureFragment(0),然后创建B,对应的itemId=1,加入到稀疏数组mFragments中,登录后position=0,系统调用ensureFragment(0),然后创建A,对应的itemId=0,加入到稀疏数组mFragments中,再调用ensureFragment(1),在稀疏数组mFragments查找到B。
简单来说:
未登录Tab[B,C],对应的position[0,1],对应的id[1,2]
登录后Tab[A,B,C],对应的position[0,1,2],对应的id[0,1,2]

到此为止结束。。。。。但其实我觉得没必要维护两个ids列表,直接通过tabs[position].hashCode().toLong()这种方式去做可能更简单。

再说一下其他的,如何获取到VIewPager2中的Framgent

方法有两个
1.通过f+id查找,因为内部添加的时候就是这么添加的,但这种不太保险,万一以后规则变了就gg了,但可能性不大
childFragmentManager.findFragmentByTag(“f” + id.toInt())

  mFragmentManager.beginTransaction()
                    .add(fragment, "f" + holder.getItemId())
                    .setMaxLifecycle(fragment, STARTED)
                    .commitNow();

2.直接通过反射拿到FragmentStateAdapter中维护的稀疏数组mFragments

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
动态删除 ViewPager 中的 Fragment,需要执行以下步骤: 1. 创建一个 FragmentStatePagerAdapter 的子类,用于管理 ViewPager 中的 Fragment。 2. 在子类中实现 getItem() 方法,该方法返回要显示的 Fragment。 3. 在子类中实现 getCount() 方法,该方法返回 Fragment 的数量。 4. 在子类中实现 getItemPosition() 方法,该方法返回 FragmentViewPager 中的位置。 5. 在子类中创建一个 ArrayList,用于存储 ViewPager 中的 Fragment。 6. 在子类的构造函数中,将 ViewPager 中的 Fragment 添加到 ArrayList 中。 7. 在子类中创建一个方法,用于从 ArrayList 中删除 Fragment。 8. 在删除 Fragment 后,调用 notifyDataSetChanged() 方法更新 ViewPager。 以下是示例代码: ```java public class MyPagerAdapter extends FragmentStatePagerAdapter { private ArrayList<Fragment> fragments = new ArrayList<>(); public MyPagerAdapter(FragmentManager fm) { super(fm); fragments.add(new Fragment1()); fragments.add(new Fragment2()); fragments.add(new Fragment3()); } @Override public Fragment getItem(int position) { return fragments.get(position); } @Override public int getCount() { return fragments.size(); } @Override public int getItemPosition(Object object) { int index = fragments.indexOf(object); if (index == -1) { return POSITION_NONE; } else { return index; } } public void removeFragment(int position) { fragments.remove(position); notifyDataSetChanged(); } } ``` 在 Activity 或 Fragment 中,可以通过以下方式删除 ViewPager 中的 Fragment: ```java MyPagerAdapter adapter = new MyPagerAdapter(getSupportFragmentManager()); viewPager.setAdapter(adapter); adapter.removeFragment(position); ``` 其中,position 为要删除FragmentViewPager 中的位置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值