在 ViewPager 的多个选项卡中使用单个片段

Posted

技术标签:

【中文标题】在 ViewPager 的多个选项卡中使用单个片段【英文标题】:Use Single Fragment in Multiple tabs of ViewPager 【发布时间】:2016-12-01 09:10:35 【问题描述】:

我正在使用ViewPager左右滑动,我也添加了选项卡,选项卡的数量取决于服务器数据,所以我不能将选项卡的数量设为固定。为此,我仅使用 Single Fragment 和 RecyclerView 在 recyclerView 中显示 JSON 数据。当第一个应用程序启动时,应该在第二个选项卡中显示的数据将显示在第一个选项卡本身中。在我滑动到 3rd Tab 并再次返回到 1st Tab 后,数据显示正确。

与 GooglePlayStore 相同。我认为只有一个片段,因为所有选项卡中的 UI 都是相同的。

这是添加 Fragment 并将数据显示到 recyclerView 的代码。

PagerAdapter.java

    private class PagerAdapter extends FragmentStatePagerAdapter 
    int mNumOfTabs;
    List<List<ProductInfo>> data;



    public PagerAdapter(FragmentManager fm, int NumofTabs, List<List<ProductInfo>> data) 
        super(fm);
        mNumOfTabs = NumofTabs;
        this.data = data;
    

    @Override
    public Fragment getItem(int position) 
       /* ProductFragment pf = ProductFragment.newInstance(data.get(position),position);
        return pf;*/

        return ProductFragment.newInstance(data.get(position),0);
    



    @Override
    public int getCount() 
        return mNumOfTabs;
    

片段.java

public class ProductFragment extends Fragment 
   private static final String ARG_PRODUCTS = "PRODS";
   private static List<ProductInfo> allProducts;
   int position = 0;
   RecyclerView prodList;


public static ProductFragment newInstance(List<ProductInfo> products,int position)         
    ProductFragment fragment = new ProductFragment();
    Bundle args = new Bundle();
    args.putParcelableArrayList(ARG_PRODUCTS, (ArrayList<ProductInfo>) products);
    args.putInt("KEY_POSITION",position);
    args.putInt("KEY_ID",id);
    fragment.setArguments(args);
    return fragment;


 @Override
 public void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    //if(isVisibleToUser)
        if (getArguments() != null) 
            allProducts = getArguments().getParcelableArrayList(ARG_PRODUCTS);
            this.position = getArguments().getInt("KEY_POSITION");
        
   // 



@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) 
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_product, container, false);
    prodList = (RecyclerView) view.findViewById(R.id.product_list);
    return view;




 @Override
 public void onViewCreated(View view, Bundle savedInstanceState) 

    prodList.setLayoutManager(new LinearLayoutManager(getActivity()));
    prodList.setAdapter(new ProductAdapter(getActivity(), allProducts));
    Log.e("ProductFragment " ,"" + allProducts.get(position).getName());

编辑: Activity.java

onCreate()
TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
    allProducts = new ArrayList<>();

    for (Category cat : catList) 
        tabLayout.addTab(tabLayout.newTab().setText(cat.getName()));
        tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
        //tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
        allProducts.add(cat.getProductsList());
    
 viewPager = (ViewPager) findViewById(R.id.pager);
    adapter = new PagerAdapter
            (getSupportFragmentManager(), tabLayout.getTabCount(), allProducts);
    viewPager.setOffscreenPageLimit(0);
    viewPager.setAdapter(adapter);

    viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
    tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() 
        @Override
        public void onTabSelected(TabLayout.Tab tab) 
            Log.e("ViewPager "," getCurrentItem() "+viewPager.getCurrentItem());
            viewPager.setCurrentItem(tab.getPosition());
        

        @Override
        public void onTabUnselected(TabLayout.Tab tab) 

        

        @Override
        public void onTabReselected(TabLayout.Tab tab) 

        
    );

 

在此处输入图片说明

【问题讨论】:

请添加您的 Activity 代码和 PagerAdapter 代码。 添加您的活动代码。 已编辑....请检查 @Drv.... 更新了问题。请检查一下伙计 @Dharvikshah 编辑过的家伙 【参考方案1】:

在 PagerAdapter 编辑如下,它可能会有所帮助:

@Override
public Fragment getItem(int position) 
   /* ProductFragment pf = ProductFragment.newInstance(data.get(position),position);
    return pf;*/

    return ProductFragment.newInstance(data.get(position),position);

并在您的 Fragment 中进行如下更改:

public class ProductFragment extends Fragment 
private static final String ARG_PRODUCTS = "PRODS";
private static List<ProductInfo> allProducts;
int position = 0;
RecyclerView prodList;
ProductAdapter productAdapter=null;


public static ProductFragment newInstance(List<ProductInfo> products,int position)         
ProductFragment fragment = new ProductFragment();
Bundle args = new Bundle();
args.putParcelableArrayList(ARG_PRODUCTS, (ArrayList<ProductInfo>) products);
args.putInt("KEY_POSITION",position);
args.putInt("KEY_ID",id);
fragment.setArguments(args);
return fragment;


@Override
public void setUserVisibleHint(boolean isVisibleToUser) 
    super.setUserVisibleHint(isVisibleToUser);
  if(isVisibleToUser)
      productAdapter.notifyDataSetChanged();
    


@Override
public void onCreate(Bundle savedInstanceState) 
super.onCreate(savedInstanceState);
//if(isVisibleToUser)
    if (getArguments() != null) 
        allProducts = getArguments().getParcelableArrayList(ARG_PRODUCTS);
        this.position = getArguments().getInt("KEY_POSITION");
    

//

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                     Bundle savedInstanceState) 
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_product, container, false);
prodList = (RecyclerView) view.findViewById(R.id.product_list);
prodList.setLayoutManager(new LinearLayoutManager(getActivity()));
productAdapter= new ProductAdapter(getActivity(), allProducts)
prodList.setAdapter(productAdapter);
        return view;
   

【讨论】:

prodList.setAdapter(new ProductAdapter(getActivity(), allProducts)); //在setUserVisibleHint的这一行发生NullPointerException productAdapter.notifyDataSetChanged(); //现在这里是 NullPointerException 请调试并尝试找出它给出空指针的原因并发布您的日志以便我也可以提供帮助。 @Drv 我正在使用相同的代码,但问题是我的最后一个 tablayout 滚动的回收器视图和前一个 tablayout 的回收器视图不滚动。【参考方案2】:

更改这一行:PagerAdapter.java

        @Override
        public Fragment getItem(int position) 
          ProductFragment fragment = new ProductFragment();
          Bundle args = new Bundle();
          args.putParcelableArrayList(ARG_PRODUCTS, (ArrayList<ProductInfo>) products);
          args.putInt("KEY_POSITION",position);
          args.putInt("KEY_ID",id);
          fragment.setArguments(args);
          return fragment;
        

并从片段中删除静态方法:

public static ProductFragment newInstance()

bcoz 这个静态方法从 viewPager 中设置最新页面的数据。和 FYI viewPager 提前在内存中加载下一页。和静态方法使它现在显示而不是将来显示。

【讨论】:

我将添加图像,它的外观 你确定。请补充。 请检查图片,第一张是应用启动并在Starrer中显示鸡蛋项目,第二张是我滑动到结束标签并再次滑动返回时,数据正确 当我点击标签而不是滑动时,数据也不正确 好的,我一有空就会尽力帮助你。保持联系:dharvikca@gmail.com。如果你能早点得到你的答复,祝你好运。【参考方案3】:

我有一个较小的问题,我使用的是具有多个 TabLayout 的单个片段。我一直在我的片段中得到错误的位置,这是 TabLayout 中的最后一个位置。

问题是将片段位置保存在静态变量或 Bundle 中将保存最后创建的片段,而 ViewPager 将在当前位置之前创建片段,这就是我们丢失当前位置的原因。

所以我为解决这个问题所做的就是创建一个局部变量来保存所创建片段的制表位置。

Kotlin 中的代码

class TabFragment : Fragment() 
private var tabPosition = 0

companion object 
    fun newInstance(tabPosition: Int): TabFragment 
        val tabFragment = TabFragment()
        tabFragment.tabPosition = tabPosition
        return tabFragment
     
  

Java 中的代码

public class TabFragment extends Fragment 
private int tabPosition = 0;
static TabFragment newInstance(int tabPosition)
    TabFragment tabFragment = new TabFragment();
    tabFragment.tabPosition = tabPosition;
    return tabFragment;
  

【讨论】:

以上是关于在 ViewPager 的多个选项卡中使用单个片段的主要内容,如果未能解决你的问题,请参考以下文章

对 ViewPager 的多个选项卡布局使用单个片段类

我在 viewpager 选项卡中的片段不刷新

如何解决片段中的 Viewpager 问题?

listview 没有在带有 viewpager 选项卡的片段中刷新

在未选择的选项卡中从片段调用方法

滚动选项卡中的片段时隐藏/显示工具栏