Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to retain ViewPager state inside a RecyclerView?

My RecyclerView contains many ViewPagers. The number of pages inside each ViewPager is constant (2). I use PagerAdapter.

When I scroll my RecyclerView, the ViewPagers lose their state and reset to the 1st page. I want to know how to retain the last selected page for each ViewPager.

For example: 1) I scroll to page 2 in my 1st ViewPager 2) I scroll the RecyclerView to the bottom and my 1st ViewPager goes out of screen. 3) I scroll to the top of the ViewPager and so my 1st ViewPager loads again. 4) My 1st ViewPager is set to 1st page instead of page 2 which I lastly scrolled to.

There are 'n' number of ViewPagers inside the RecyclerView and I want to retain all their states regardless of reloading due to RecyclerView.

How to solve this logic?

like image 575
Sanju Avatar asked Dec 14 '15 19:12

Sanju


1 Answers

Well, I wrote little bit brute-force solution for this.

My PagerAdapter:

public class ViewPagerAdapter extends PagerAdapter {

    @Override
    public int getCount() {
        return 2;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        FrameLayout layout = new FrameLayout(container.getContext());
        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
                FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
        layout.setLayoutParams(layoutParams);

        layout.setBackgroundColor(position % 2 == 0 ? Color.RED : Color.BLUE);
        container.addView(layout);
        return layout;
    }

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

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

(so we the visually "state" differs in it's color - it's red in first position and blue in the second position)

The RecyclerViewAdapter looks like:

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    public HashMap<Integer, Integer> viewPageStates = new HashMap<>();

    public RecyclerViewAdapter() {}

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        return new ViewHolder(new ViewWithViewPager(viewGroup.getContext()));
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        ((ViewWithViewPager) holder.itemView).refreshState(position, viewPageStates.containsKey(position)? viewPageStates.get(position) : 0);
    }

    @Override
    public int getItemCount() {
        return 42;
    }

    @Override
    public void onViewRecycled(RecyclerView.ViewHolder holder) {
        ViewWithViewPager recycledViewPager = ((ViewWithViewPager)holder.itemView);
        viewPageStates.put(recycledViewPager.viewPosition, recycledViewPager.viewPager.getCurrentItem());
        super.onViewRecycled(holder);
    }

    public class ViewHolder extends RecyclerView.ViewHolder {

        public ViewHolder(View itemView) {
            super(itemView);
        }
    }
}   

I.e. every time we bind RecyclerView's ViewHolder, we pass the current state of the viewpager(from viewPageStates) and its order in RecyclerView's dataset. Once it's recycled - we read its current page state and saving it into HashMap viewPageStates.

The last piece - the ViewWithViewPager

public class ViewWithViewPager extends FrameLayout {

    ViewPager viewPager;
    int viewPosition = 0;

    public ViewWithViewPager(Context context) {
        super(context);
        LayoutInflater.from(context).inflate(R.layout.item_layout, this);
        viewPager = (ViewPager) findViewById(R.id.viewPager);
        viewPager.setAdapter(new ViewPagerAdapter());
    }

    public void refreshState(int position, int selectedPage) {
        viewPosition = position;
        viewPager.setCurrentItem(selectedPage);
    }
}

I.e. in refreshState we set ViewPager to the proper page

like image 114
Konstantin Loginov Avatar answered Oct 16 '22 13:10

Konstantin Loginov