programforjoy
programforjoy

Reputation: 499

android:How can I call setAdapter for ViewPager inside the method onPageSelected?

My adapter for the ViewPager needs to be reset according to the current active page.I want to do it using OnPageChangeListener. A part of the code of my adapter is like:

    class CustomPagerAdapter extends PagerAdapter {
            static int currpage = 0; // current selected page
            ......
            @Override
            public Object instantiateItem(ViewGroup collection, int position) {     
                LayoutInflater inflater = LayoutInflater.from(mContext);
                View layout = inflater.inflate(R.layout.layout_home_viewpager, collection, false);

               // some code that changes layout dynamically    
               // according to variable position and currpage
               ......

               collection.addView(layout);
               return layout;
            }
    }

And here is the code for my viewpager(inside OnCreateView of a fragment):

    ViewPager.OnPageChangeListener onPageChangeListener = new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

        }

        @Override
        public void onPageSelected(int position) {
            CustomPagerAdapter.currpage = position;
        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    };
    viewPager.addOnPageChangeListener(onPageChangeListener);
    viewPager.setAdapter(customPagerAdapter);

The following code will only be called once(When creating view of the fragment):

     viewPager.setAdapter(customPagerAdapter);

I intend to call setadapter whenever the active is changed.But if I change the code to this :

    @Override
    public void onPageSelected(int position) {
        CustomPagerAdapter.currpage = position; // flag for setAdapter
        viewPager.setAdapter(customPagerAdapter);
    }

the viewpager will be unable to slide.

Since the only way to detect page changing is register a listener to viewPager and we can't call setAdapter inside the method of our listener, What will be the best way to reset adapter for viewpager when the selected page is changed ?

Upvotes: 1

Views: 1564

Answers (3)

programforjoy
programforjoy

Reputation: 499

I have found a solution to my posted question. Check this question: ViewPager PagerAdapter not updating the View

All we need is to call setTag() method in instantiateItem() when instantiating a new view. Then you can use findViewWithTag() to find the view you want to update.

Code will be like:

     public Object instantiateItem(ViewGroup collection, int position) {     
            LayoutInflater inflater = LayoutInflater.from(mContext);
            View layout = inflater.inflate(R.layout.layout_home_viewpager, collection, false);
            layout.setTag(position);


            ......

            collection.addView(layout);
            return layout;
        }        

    @Override
    public void onPageSelected(int position) {
            View layout = viewPager.findViewWithTag(position);
            // code that updates the selected page ......
    }

Upvotes: 0

user3629714
user3629714

Reputation:

I don't quite understand what you mean with "needs to be reset". If you reset the adapter the viewpager will go back to the first page, which is totally not what you want the viewpager to do when the user changes the page.

But the problem is deeper. A ViewPager doesn't work like a ListView, it doesn't recycle its views, or rebinds them according to a change in the underlying dataset. It's basically just a ViewGroup with paging and swiping functionality. In practice, what this means is that you need to keep track of your views, their positions and bind them to your data outside of the onInstantiate and onDestroy methods, so basically your approach isn't optimal considering the limitations of the API you are using.

My suggestion would be to change your adapter and hold a reference to your views using a List, move your view logic to the outside of your instantiate method and call it everytime a page changes.

Here's a functioning example:

 class CustomPagerAdapter extends PagerAdapter {
        List<View> mViews = new ArrayList<>;
        ......
        @Override
        public Object instantiateItem(ViewGroup collection, int position) {     
            LayoutInflater inflater = LayoutInflater.from(mContext);
            View layout = inflater.inflate(R.layout.layout_home_viewpager, collection, false);
           mViews.add(layout);
           collection.addView(layout);
           populateView(layout);
           return layout;
        }

        public void populateView(int position){
           if(position < mView.size()){
              populateView(mViews.get(position));
           }
        }

        private void populateView(View layout){
           // some code that changes layout dynamically    
           // according to variable position and currpage
           ......
        }
}

And then, on your listener:

@Override
public void onPageSelected(int position) {
    customPagerAdapter.populateView(position);
}

This should fix your issue.

Upvotes: 1

Vladislav Sazanovich
Vladislav Sazanovich

Reputation: 537

You could invoke setAdapter() when user finished slide.

@Override
public void onPageScrollStateChanged(int state) {
    if (state == SCROLL_STATE_IDLE) {
        setAdapter(adapter);
    }
}

Upvotes: 1

Related Questions