Infinite Scrolling Image ViewPager

后端 未结 7 838
Happy的楠姐
Happy的楠姐 2020-11-27 17:33

As documented by Google, the Gallery class was deprecated in API level 16. This widget is no longer supported. Other horizontally scrolling widgets include HorizontalScrollV

7条回答
  •  南笙
    南笙 (楼主)
    2020-11-27 17:44

    I found another solution, based on Shlomi Hasin and antonyt answers, without modifying collection.

    ViewPager yourPager;
    PagerAdapter yourAdapter;
    //....
    EndlessPagerAdapter endlessPagerAdapter = new EndlessPagerAdapter(yourAdapter, yourPager);
    yourPager.setAdapter(endlessPagerAdapter);
    yourPager.setCurrentItem(1);//for correct first page
    

    Full class:

    public class EndlessPagerAdapter extends PagerAdapter {
    
    private PagerAdapter adapter;
    
    public EndlessPagerAdapter(PagerAdapter adapter, ViewPager viewPager) {
        this.adapter = adapter;
        viewPager.addOnPageChangeListener(new SwapPageListener(viewPager));
    }
    
    @Override
    public int getCount() {
        return adapter.getCount() + 2;
    }
    
    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        if (adapter.getCount() < 2) {
            adapter.instantiateItem(container, position);
        }
    
        int newPosition;
        if (position == 0) {
            newPosition = adapter.getCount() - 1;
        } else if (position >= getCount() - 1) {
            newPosition = 0;
        } else {
            newPosition = position - 1;
        }
        return adapter.instantiateItem(container, newPosition);
    }
    
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        adapter.destroyItem(container, position, object);
    }
    
    @Override
    public void finishUpdate(ViewGroup container) {
        adapter.finishUpdate(container);
    }
    
    @Override
    public boolean isViewFromObject(View view, Object object) {
        return adapter.isViewFromObject(view, object);
    }
    
    @Override
    public void restoreState(Parcelable bundle, ClassLoader classLoader) {
        adapter.restoreState(bundle, classLoader);
    }
    
    @Override
    public Parcelable saveState() {
        return adapter.saveState();
    }
    
    @Override
    public void startUpdate(ViewGroup container) {
        adapter.startUpdate(container);
    }
    
    @Override
    public CharSequence getPageTitle(int position) {
        return adapter.getPageTitle(position);
    }
    
    @Override
    public float getPageWidth(int position) {
        return adapter.getPageWidth(position);
    }
    
    @Override
    public void setPrimaryItem(ViewGroup container, int position, Object object) {
        adapter.setPrimaryItem(container, position, object);
    }
    
    @Override
    public void unregisterDataSetObserver(DataSetObserver observer) {
        adapter.unregisterDataSetObserver(observer);
    }
    
    @Override
    public void registerDataSetObserver(DataSetObserver observer) {
        adapter.registerDataSetObserver(observer);
    }
    
    @Override
    public void notifyDataSetChanged() {
        adapter.notifyDataSetChanged();
    }
    
    @Override
    public int getItemPosition(Object object) {
        return adapter.getItemPosition(object);
    }
    
    private class SwapPageListener implements ViewPager.OnPageChangeListener {
    
        private ViewPager viewPager;
    
        SwapPageListener(ViewPager viewPager) {
            this.viewPager = viewPager;
        }
    
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    
        }
    
        @Override
        public void onPageSelected(int position) {
    
        }
    
        @Override
        public void onPageScrollStateChanged(int state) {
            if (state == ViewPager.SCROLL_STATE_IDLE) {
                PagerAdapter pagerAdapter = viewPager.getAdapter();
                if (pagerAdapter != null) {
                    int itemCount = pagerAdapter.getCount();
                    if (itemCount < 2) {
                        return;
                    }
                    int index = viewPager.getCurrentItem();
                    if (index == 0 ) {
                        viewPager.setCurrentItem(itemCount - 2, false);
                    } else if (index == itemCount - 1) {
                        viewPager.setCurrentItem(1, false);
                    }
                }
            }
        }
    }}
    

    How it works:

    We have some collection

    then add two additional items to it

    show first element on last position and last element on first position

    add listener and swap pages on event, from 4 to 1 and from 0 to 3

    thats all.

    I would not advise you to apply animation there or heavy layouts, it can be lagging when elements swap.(maybe, I did not encounter any lags)

    Also don't set this adapter to pager more than once, or move SwapPageListener to external class and set it in initialization block.

提交回复
热议问题