How to implement viewpager in recyclerview
Asked Answered
R

1

8

I want to create ViewPager (holder) in RecyclerView when I create it and scroll view pager some row then I scroll RecyclerViewand some element that reuse component.

My Code:

MainActivity

public class MainActivity extends AppCompatActivity {
    private RecyclerView rcv;
    private LinearLayoutManager llom;
    private MainActivityAdapter adapter;
    private List<String> list1 = new ArrayList<>();
    private List<String> list2 = new ArrayList<>();
    private List<String> list3 = new ArrayList<>();
    private List<String> list4 = new ArrayList<>();
    private List<String> list5 = new ArrayList<>();
    private List<String> list6 = new ArrayList<>();
    private List<String> list7 = new ArrayList<>();
    private List<String> list8 = new ArrayList<>();
    private List<String> list9 = new ArrayList<>();
    private List<String> list10 = new ArrayList<>();
    private HashMap<Integer, List<String>> hashMap = new HashMap<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        list1.add("1");
        list1.add("2");
        list1.add("3");
        list1.add("4");
        list1.add("5");

        list2.add("1");
        list2.add("2");
        list2.add("3");
        list2.add("4");
        list2.add("5");

        list3.add("1");
        list3.add("2");
        list3.add("3");
        list3.add("4");
        list3.add("5");

        list4.add("1");
        list4.add("2");
        list4.add("3");
        list4.add("4");
        list4.add("5");

        list5.add("1");
        list5.add("2");
        list5.add("3");
        list5.add("4");
        list5.add("5");

        list6.add("1");
        list6.add("2");
        list6.add("3");
        list6.add("4");
        list6.add("5");

        list7.add("1");
        list7.add("2");
        list7.add("3");
        list7.add("4");
        list7.add("5");

        list8.add("1");
        list8.add("2");
        list8.add("3");
        list8.add("4");
        list8.add("5");

        list9.add("1");
        list9.add("2");
        list9.add("3");
        list9.add("4");
        list9.add("5");

        list10.add("1");
        list10.add("2");
        list10.add("3");
        list10.add("4");
        list10.add("5");

        hashMap.put(0,list1);
        hashMap.put(1,list2);
        hashMap.put(2,list3);
        hashMap.put(3,list4);
        hashMap.put(4,list5);
        hashMap.put(5,list6);
        hashMap.put(6,list7);
        hashMap.put(7,list8);
        hashMap.put(8,list9);
        hashMap.put(9,list10);

        rcv = (RecyclerView) findViewById(R.id.rcv);
        llom = new LinearLayoutManager(this);
        rcv.setLayoutManager(llom);
        adapter = new MainActivityAdapter(this, hashMap);
        rcv.setAdapter(adapter);

    }
}

MainActivityAdapter

public class MainActivityAdapter extends RecyclerView.Adapter {
    private Context context;
    private static final int TEST = 0;
    private HashMap<Integer, List<String>> hashMap;

    public MainActivityAdapter(Context context, HashMap<Integer, List<String>> hashMap) {
        this.context = context;
        this.hashMap = hashMap;

    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new VpListItem(new ViewPagerListItem(context));


    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        ((VpListItem) holder).fillData(hashMap.get(position), position);

    }

    @Override
    public int getItemCount() {
        return hashMap.size();
    }


    public static class VpListItem extends RecyclerView.ViewHolder {
        private ViewPagerListItem otherArticlesListItem;

        public VpListItem(ViewPagerListItem itemView) {
            super(itemView);
            this.otherArticlesListItem = itemView;
        }

        public void fillData(List<String> list, int position) {
            otherArticlesListItem.fillData(list, position);

        }


    }
}

ViewPagerListItem

public class ViewPagerListItem extends RelativeLayout {
    private Context context;
    private WrapContentViewPager vp;
    private ViewPagerAdapter adapter;
    private List<String> list = new ArrayList<>();


    public ViewPagerListItem(Context context) {
        super(context);
        this.context = context;
        setupView();
    }

    public ViewPagerListItem(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        setupView();
    }

    public ViewPagerListItem(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        setupView();
    }

    private void setupView() {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View view = inflater.inflate(R.layout.vp_list_item, this, true);
        vp = (WrapContentViewPager) view.findViewById(R.id.vp);
        adapter = new ViewPagerAdapter(context, list);
        vp.setAdapter(adapter);


    }

    public void fillData(List<String> list, int id) {
        vp.setId(id);
        this.list.addAll(list);
        adapter.notifyDataSetChanged();


    }
}

ViewPagerAdapter

public class ViewPagerAdapter extends PagerAdapter {
    private Context context;
    private List<String> list;


    public ViewPagerAdapter(Context context, List<String> list) {
        this.context = context;
        this.list = list;


    }

    @Override
    public int getCount() {
        return list.size();
    }

    @Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == (View) object;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView((View) object);
    }

    @Override
    public Object instantiateItem(ViewGroup container, final int position) {

        CardListItem cardListItem = new CardListItem(context);
        cardListItem.fillData(list.get(position));
        container.addView(cardListItem);
        return cardListItem;
    }
}


CardListItem

    public class CardListItem extends LinearLayout {
    private Context context;
    private TextView tv;

    public CardListItem(Context context) {
        super(context);
        this.context = context;
        setupView();
    }

    public CardListItem(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        setupView();
    }

    public CardListItem(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        setupView();
    }

    private void setupView() {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View view = inflater.inflate(R.layout.card_list_item, this, true);
        tv = (TextView) view.findViewById(R.id.tv);


    }

    public void fillData(String text) {
        tv.setText(text);


    }
}

Then I scroll RecyclerView some time it lag . And I scroll ViewPager then I scroll RecyclerView some element (ViewPager that not scroll) change according to ViewPager that I scroll

Thank you.

Rockefeller answered 20/9, 2016 at 6:31 Comment(0)
L
7

I've created sample project in which there is recycler view two types of items:

  1. Simple Text View
  2. View Pager

You can check it here

Inflation of these view is done in Adapter View:

 @Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    RecyclerView.ViewHolder viewHolder = null;
    LayoutInflater inflater = LayoutInflater.from(parent.getContext());

    switch (viewType) {

        case VIEW_TYPE_TEXT:
            View userView = inflater.inflate(R.layout.item_recycler_text, parent, false);
            viewHolder = new TextItemHolder(userView);
            break;

        case VIEW_TYPE_PAGER:
            View blockbusterView = inflater.inflate(R.layout.item_recycler_pager, parent, false);
            viewHolder = new PagerItemHolder(blockbusterView);
            break;
    }

    return viewHolder;
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

    switch (holder.getItemViewType()) {

        case VIEW_TYPE_TEXT:
            TextItemHolder textHolder = (TextItemHolder) holder;
            configureTextItem(textHolder, position);
            break;

        case VIEW_TYPE_PAGER:
            PagerItemHolder pagerHolder = (PagerItemHolder) holder;
            configurePagerHolder(pagerHolder, position);
            break;
    }
}

private void configureTextItem(TextItemHolder holder, int position) {

    Data data = mDataList.get(position);

    if (!Check.isEmpty(data.getTextItem()))
        holder.tvTitle.setText(data.getTextItem());
}

private void configurePagerHolder(PagerItemHolder holder, int position) {

    Data data = mDataList.get(position);

    CustomPagerAdapter adapter = new CustomPagerAdapter(data.getPagerItemList(), mContext);
    holder.viewPager.setAdapter(adapter);
}

Hope it helps.. !!

Edited:

For restoring previously scrolled state in ViewPager, when an item in Recycler View we have to:

  1. Override onViewRecycled method of RecyclerView.Adapter
  2. Maintain a hash for previous position scrolled to. And values can be called as:

if (mViewPageStates.containsKey(position)) holder.viewPager.setCurrentItem(mViewPageStates.get(position));

Luciferin answered 20/9, 2016 at 13:8 Comment(8)
Ok,thankyou but when I scroll viewpager to Harneev 2 and scroll recyclerview to other position then scroll to viewpager that Harneev 2 the results show that back to Harneev 1 . I want to save position in viewpager.Rockefeller
@WuttipongKhemphetjetsada - updated in github repository :)Luciferin
I use your project to test . not change anything but result don't match my requirement. My requirement is when you scroll viewpager to position 2 then you scroll recyclerview to bottom and finally you scroll recyclerview to item ( viewpager that you scroll to position 2 ) not change position . Now viewpager will refresh when you scroll back . Thankyou :)Rockefeller
@WuttipongKhemphetjetsada - if it helps you, please accept answer :)Luciferin
Ok, but I want to save state in viewpager when you scroll recyclerview . Can you help me please? ThankyouRockefeller
@WuttipongKhemphetjetsada - save state means ? you want your recycler items not to get refreshed ? If this is the case, then you can increase limit n this method: recyclerView.getRecycledViewPool().setMaxRecycledViews(0, 10); . but this wont be a good approach as views should be recycled as it saves memory.Luciferin
we have implemented in a pretty similar way and we are coming across an issue in which if we scroll away from the view-pager row and scroll back to it, then the first page swipe is not gradual i.e without animation, it just changes the page in a flick. The working is normal for rest of the page swipes. Any guesses what might be the reason ?Austreng
@Austreng what i can understand from your comment is that you want when viewpager is loaded in view then it should animate while moving to first position rather then just reload without animation. If that is the case then i would like to add that when recycler item comes in view port then it is recreated and not refreshed. So it makes sense to completely recreate the view rather than refresh the previous.Luciferin

© 2022 - 2024 — McMap. All rights reserved.