Android 无限循环且支持自动滚动的ViewPager

本文介绍了一种基于ViewPager的无限循环适配器的设计与实现方法。通过在两端添加额外的视图,使得用户可以无缝地从末页跳转到首页,反之亦然。此外,还实现了自动滚动功能,提升了用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

无限循环思路:

1. 添加最后一条数据到第一条,添加第一条数据到最后一条; 

2.滚动到最后一页,自动跳到第二页(视觉上的第一页),滚动到第一页,自动跳转至倒数第二页(视觉上最后一页);

3.初始设置滚动到第二页(视觉上的第一页);

自动滚动思路:

使用定时器自动向右滚动。


具体实现

public class LoopPagerAdapter extends PagerAdapter implements ViewPager.OnPageChangeListener {
    private static final String TAG = "LoopPagerAdapter";
    private Context context;
    /**是否循环*/
    private boolean isLoop;
    /**viewpager*/
    private ViewPager viewPager;

    /**view布局文件*/
    private List<Integer> resources;
    /**View数据源*/
    private List<View> views;
    /**当前页面*/
    private int currentPosition = 0;

    /**定时器*/
    private Timer timer;
    private MyHandler handler;

    /**
     *
     * @param context 上下文
     * @param resources view布局列表
     * @param vp viewpager
     */
    public LoopPagerAdapter(Context context, List<Integer> resources, ViewPager vp){
        this.context = context;
        this.resources = resources;
        this.viewPager = vp;

        init();
    }

    /**
     *
     * @param context 上下文
     * @param resources view布局列表
     * @param isLoop 是否循环滚动
     * @param vp viewpager
     */
    public LoopPagerAdapter(Context context, List<Integer> resources, boolean isLoop, ViewPager vp){
        this.context = context;
        this.context = context;
        this.resources = resources;
        this.isLoop = isLoop;
        this.viewPager = vp;

        addLoopViews();
        init();
    }

    private void addLoopViews(){
        if(views == null){
            views = new ArrayList<>();
        }
        LayoutInflater inflater = LayoutInflater.from(context);
        for(Integer id : resources){
            views.add(inflater.inflate(id, null));
        }

        int size = views.size();
        //如果不是循环,view数量只有1个,则不处理
        if(!isLoop || size <= 1){
            return;
        }
        //第一页view
        View firstView = inflater.inflate(resources.get(0), null);
        //尾页view
        View endView = inflater.inflate(resources.get(size-1), null);
        //添加一个尾页到第一页
        views.add(0, endView);
        //添加一个首页到最后一页
        views.add(firstView);
    }

    private void init(){
        viewPager.setAdapter(this);
        viewPager.addOnPageChangeListener(this);
        viewPager.setCurrentItem(1, false);
    }

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

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

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        View view = views.get(position);
        container.addView(view);
        return views.get(position);
    }

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

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {
        this.currentPosition = position;
    }

    @Override
    public void onPageScrollStateChanged(int state) {
        //如果还在滑动中或非循环不做处理
        if(state != ViewPager.SCROLL_STATE_IDLE || !isLoop){
            return;
        }

        //如果当前页面为第一张,则设置页面为倒数第二张
        if(currentPosition == 0){
            viewPager.setCurrentItem(views.size()-2, false);
        }else if(currentPosition == views.size() - 1){//若当前为倒数第一张,设置页面为第二张
            viewPager.setCurrentItem(1, false);
        }
    }

    /**
     * 开始自动滚动
     * @param delay 等待时间
     * @param period 间隔时间
     */
    public void startAutoScrollPage(long delay, long period){
        handler = new MyHandler(this);
        timer = new Timer();
        timer.schedule(new MyTask(this), delay, period);
    }

    /**
     * 停止自动滚动
     */
    public void stopAutoScrollPage(){
        if(timer != null){
            timer.cancel();
        }
        if(handler != null){
            handler.removeCallbacksAndMessages(null);
        }
    }

    /**
     * 自动滚动handler
     */
    private static class MyHandler extends Handler {
        private WeakReference<LoopPagerAdapter> weakReference;

        public MyHandler(LoopPagerAdapter adapter){
            weakReference  = new WeakReference<>(adapter) ;
        }

        @Override
        public void handleMessage(Message msg) {
            if(weakReference.get() == null){
                return;
            }
            LoopPagerAdapter adapter = weakReference.get();
            adapter.viewPager.arrowScroll(adapter.viewPager.FOCUS_RIGHT);
        }
    }

    /**
     * 定时器
     */
    private static class MyTask extends TimerTask {
        private WeakReference<LoopPagerAdapter> weakReference;

        public MyTask(LoopPagerAdapter adapter){
            weakReference  = new WeakReference<>(adapter);
        }

        @Override
        public void run() {
            if(weakReference.get() == null){
                return;
            }
            LoopPagerAdapter adapter = weakReference.get();
            adapter.handler.sendMessage(new Message());
        }
    }
}

使用

vp = (ViewPager) findViewById(R.id.activity_main_vp);
        List<Integer> ids = new ArrayList<>();
        ids.add(R.layout.view_vp1);
        ids.add(R.layout.view_vp2);
        ids.add(R.layout.view_vp3);

        LoopPagerAdapter adapter = new LoopPagerAdapter(getApplicationContext(), ids, true, vp);
        adapter.startAutoScrollPage(3000, 3000);

效果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值