使用多个ViewPager+Fragment布局相同情况下Fragment不显示问题

首先来说说我今天遇到的那些坑。

使用多个ViewPager+Fragment布局相同情况下Fragment不显示问题_第1张图片

如果在RecyclerView里面的item同时出现三个 ViewPager+TabLayout+Fragment的布局的话,

并且你写入了数据,如果没有什么以外的话,出来的效果是这样的。

使用多个ViewPager+Fragment布局相同情况下Fragment不显示问题_第2张图片

我基本上都是已经写入了假数据的,可是第二和第三个ViewPager只能看到title。你没看错我今天遇到的坑就是这样的。

第一次遇到这种问题,我还能怎么办我也很绝望啊。

使用多个ViewPager+Fragment布局相同情况下Fragment不显示问题_第3张图片

然后只能埋头研究了,经过一晚上的奋斗,终于得知道了bug所在。其实看了一些源码+上一些猜想才想到怎么修这个bug的。

那么废话不多说,直接上代码把。首先我们解决第一部分,先看看FragmentPagerAdapter源码里面的的instantiateItem方法

   @Override
    public Object instantiateItem(ViewGroup container, int position) {
        if (mCurTransaction == null) {
            mCurTransaction = mFragmentManager.beginTransaction();
        }

        final long itemId = getItemId(position);

        // Do we already have this fragment?
        String name = makeFragmentName(container.getId(), itemId);
        Fragment fragment = mFragmentManager.findFragmentByTag(name);
        if (fragment != null) {
            if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment);
            mCurTransaction.attach(fragment);
        } else {
            fragment = getItem(position);
            if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment);
            mCurTransaction.add(container.getId(), fragment,
                    makeFragmentName(container.getId(), itemId));
        }
        if (fragment != mCurrentPrimaryItem) {
            fragment.setMenuVisibility(false);
            fragment.setUserVisibleHint(false);
        }

        return fragment;
    }
在String name = makeFragmentName(container.getId(), itemId);

和mCurTransaction.add(container.getId(), fragment,makeFragmentName(container.getId(), itemId));

这句代码中我们发现fragment都是以container的id+itemId(gettemId()) 两个参数计算出来作为fragment的储存的tag key值

FragmentManager是activity自己创建的东西,你又不可能自己new一个,然后呢所有的Fragment都塞进FragmentManager

取的时候是根据布局的id取的,而我又用了三个相同的布局,那么问题就简单了,直接存储重复id然后不论你创建多少个都

只能取出你创建的第一个viewPage的item布局

解决办法:

重写继承了FragmentPagerAdapter的getItemId()方法如下

 @Override
    public long getItemId(int position) {
        return pageData.get(position).hashCode();
    }

然而你会发现问题还是没有解决,那么我们再来继续解决问题。

第二个问题跟第一个相似,那就是instantiateItem下面的ViewGroup。

请仔细看此方法

mCurTransaction.add(container.getId(), fragment,makeFragmentName(container.getId(), itemId));
有没有发现这里还有一个getId。那么问题来了,你仔细想看,既然Fragment都是在一个池子里面的,那么你将Fragment根据ID塞进 ViewGroup里面的话是啥情况,先说明ViewGroup其实就是ViewPager。我们三个item都是ViewPager。那么你直接根据id塞入的话,activity回去寻找id为你添加进入改id的ViewGroup的控件,可是我们这里有三个。

so?明白了没?

只能设置给第一个ViewPager.

所以不论你添加多少个ViewPager 下面都不会有数据显示出来就是这个问题。

解决办法:

RecyclerView创建ViewHolder初始化所有view控件的时候设置viewPager这么一句

viewPager.setId(datas.get(position).hashCode());
然后问题就基本上解决了。

使用多个ViewPager+Fragment布局相同情况下Fragment不显示问题_第4张图片


是不是很惊喜很意外,这么简单的bug让我长篇大论啰嗦了这么多。

使用多个ViewPager+Fragment布局相同情况下Fragment不显示问题_第5张图片

你可能感兴趣的:(Android开发)