Use Single Fragment in Multiple tabs of ViewPager

2019-03-22 07:07发布

问题:

I am using ViewPager to slide left and right, I have also added the tabs, The number of tabs is depends on the server data, So, I cannot make the number of tabs as Fixed. To do this I used only Single Fragment and a RecyclerView to display JSON Data in the recyclerView. When First app launches, the data which should be shown in 2nd tab is getting displayed in 1st Tab itself. After I swipe to 3rd Tab and come Back again to 1st Tab, then the data is displaying correctly.

It is as same as GooglePlayStore. I think there is only one fragment, because the UI is same in all the tabs.

Here is the code to Add Fragment and displaying data to 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;
    }
}

Fragment.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());
}

EDITED: 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) {

        }
    });

 }

enter image description here

回答1:

In PagerAdapter edit as below, it might help:

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

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

And in your Fragment make changes as below:

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;
   }
}


回答2:

change this line in : 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;
        }

and remove static method from fragment as :

public static ProductFragment newInstance()

bcoz this static method set data of the latest page from viewPager. and FYI viewPager load next page in memory in advance. and static method makes it show now rather then show in future.