ViewPager循环滑动及自动播放

对于经常使用viewpager的人,应该清楚一般的viewpager在滑动到最右端或者最左端时,就不能继续往下滑动了,从用户的角度来看,这点的体验很不好,用户可能期待的是当我滑动到最后一页的时候,可以继续滑动,并滑动到第一页,所以我们需要实现viewpager的循环滑动。在网上也找了很多例子,基本上比较实用的方法就是一种,这个我们后边就是讲这种方法,并且在此基础上添加了可以控制viewpager是否需要自动循环滑动的功能,先上效果图:
这里写图片描述

接下来,我们来分析实现的方法:
假如说我们的viewpager中现在有三张图片A, B, C, 要实现滑动的C的时候,我们能继续滑动并且滑动到A,网上的方法是在viewpager最开始的位置插入最后一张图片C,在viewpager最后的位置插入最开始的图片A,这样,我们viewpager中的图片就变为C, A, B, C, A。当我们滑动最后一张C的时候,这个时候在滑动的话,是可以继续滑动的,因为C后边还有一个A,但是当滑动完成后,需要将下标为4的A改为下标为1的A,这样后,当A在滑动到它的下一页时才会出现B,否则将不能继续向右滑动(因为此时的A已经是viewpager中的最后一个了)。向左滑动是一样的道理。

接下来,就是上代码,先来看我们自定义的viewpager类(这是网上的类,我只是修改了一下):

package com.example.test_loop_viewpager;

import android.content.Context;
import android.database.DataSetObserver;
import android.os.Handler;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

public class CycleViewPager extends ViewPager {

    private InnerPagerAdapter mAdapter;
    private int mCurrentIndex = 1;
    //播放标志
    private boolean isPlay = false; 
    private final int PLAY = 0x123;
    //默认页面之间的切换时间
    private long mDelayTime = 2000;

    private Handler mHandler = new Handler(){
        public void handleMessage(android.os.Message msg) {
            if (msg.what == PLAY){
                setCurrentItem(mCurrentIndex);
                if (isPlay){
                    play();
                }
            }
        }
    };

    public CycleViewPager(Context context) {
        super( context);
        setOnPageChangeListener( null);
    }

    public CycleViewPager(Context context, AttributeSet attrs) {
        super( context, attrs);
        setOnPageChangeListener( null);
    }

    @Override
    public void setAdapter(PagerAdapter arg0) {
        mAdapter = new InnerPagerAdapter( arg0);
        super.setAdapter( mAdapter);
        setCurrentItem(1);
    }

    /**
     * 开始播放
     * @param delayMillis
     */
    public void startPlay( long delayMillis){
        isPlay = true;
        mDelayTime = delayMillis;
        play();
    }

    private void play(){
        mCurrentIndex ++;
        mCurrentIndex = mCurrentIndex % mAdapter.getCount();
        if (mCurrentIndex == 0){
            mCurrentIndex += 2;
        }
        mHandler.sendEmptyMessageDelayed(PLAY, mDelayTime);
    }

    /**
     * 停止播放
     */
    public void stopPlay(){
        isPlay = false;
    }

    @Override
    public void setOnPageChangeListener(OnPageChangeListener listener) {
        super.setOnPageChangeListener( new InnerOnPageChangeListener( listener));
    }

    private class InnerOnPageChangeListener implements OnPageChangeListener {

        private OnPageChangeListener listener;
        private int position;

        public InnerOnPageChangeListener(OnPageChangeListener listener) {
            this.listener = listener;
        }

        @Override
        public void onPageScrollStateChanged(int arg0) {
            if(null != listener) {
                listener.onPageScrollStateChanged( arg0);
            }
            if(arg0 == ViewPager.SCROLL_STATE_IDLE) {
                if(position == mAdapter.getCount() - 1) {
                    setCurrentItem( 1, false);
                }
                else if(position == 0) {
                    setCurrentItem(mAdapter.getCount() - 2, false);
                }
            }
        }

        @Override
        public void onPageScrolled(int arg0, float arg1, int arg2) {
            if(null != listener) {
                listener.onPageScrolled( arg0, arg1, arg2);
            }
        }

        @Override
        public void onPageSelected(int arg0) {
            mCurrentIndex = arg0;
            position = arg0;
            if(null != listener) {
                listener.onPageSelected( arg0);
            }
        }
    }

    private class InnerPagerAdapter extends PagerAdapter {

        private PagerAdapter adapter;

        public InnerPagerAdapter(PagerAdapter adapter) {
            this.adapter = adapter;
            adapter.registerDataSetObserver( new DataSetObserver() {

                @Override
                public void onChanged() {
                    notifyDataSetChanged();
                }

                @Override
                public void onInvalidated() {
                    notifyDataSetChanged();
                }

            });
        }

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

        @Override
        public boolean isViewFromObject(View arg0, Object arg1) {
            return adapter.isViewFromObject( arg0, arg1);
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            if(position == 0) {
                position = adapter.getCount() - 1;
            }
            else if(position == adapter.getCount() + 1) {
                position = 0;
            }
            else {
                position -= 1;
            }
            return adapter.instantiateItem( container, position);
        }

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

    }
}

这个类里有两个内部类,InnerOnPageChangeListener和InnerPagerAdapter, 这两个内部类是对我们传进来的onPagerChangeListener和PagerAdapter做了一下包装,且处理了一些我们自己的逻辑业务。并且提供了两个接口startPaly(long delayMillis)和stopPlay()来播放图片和停止播放,一般我们在onResume()和onPause()方法调用这两个方法。

再来看给viewpager设置数据源的adapter类:

package com.example.test_loop_viewpager;

import android.content.Context;
import android.provider.MediaStore.Images.ImageColumns;
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2016/2/2.
 */
public class MyPagerAdapter extends PagerAdapter {
    private Context mContext;
    private List<ImageView> mImageViewCache = new ArrayList<ImageView>();
    private List<Integer> mImageUrl;

    public MyPagerAdapter(Context context, List<Integer> imageUrl){
        this.mContext = context;
       mImageUrl = imageUrl;
    }

    @Override
    public int getCount() {
        return mImageUrl != null ? mImageUrl.size() : 0;
    }

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

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        ImageView iv = (ImageView) object;
        container.removeView(iv);
        mImageViewCache.add(iv);
    }

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

        ImageView image = null;
        if (mImageViewCache.isEmpty()){
            image = new ImageView(mContext);
            image.setScaleType(ImageView.ScaleType.CENTER_CROP);
        }else {
            image = mImageViewCache.remove(0);
        }

        image.setImageResource(mImageUrl.get(position));
        container.addView(image);
        return image;
    }

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

这个类没什么说的,跟我们平时写Viewpager时写的PagerAdapter一样

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.example.test_loop_viewpager.CycleViewPager
        android:id="@+id/id_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </com.example.test_loop_viewpager.CycleViewPager>
</RelativeLayout>

在MainActivity中调用:

package com.example.test_loop_viewpager;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.provider.MediaStore.Images;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.Window;
import android.widget.ImageView;

public class MainActivity extends Activity {
    private CycleViewPager mPager;
    private MyPagerAdapter mPagerAdapter;
    private List<Integer> mImages = new ArrayList<Integer>();


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);

        mPager = (CycleViewPager) findViewById(R.id.id_pager);
        setData();
        mPagerAdapter = new MyPagerAdapter(this, mImages);
        mPager.setAdapter(mPagerAdapter);

    }

    private void setData() {
        mImages.add(R.drawable.image1);
        mImages.add(R.drawable.image2);
        mImages.add(R.drawable.image3);
        mImages.add(R.drawable.image4);
        mImages.add(R.drawable.image5);
    }

    @Override
    protected void onResume() {
        mPager.startPlay(2000);
        super.onResume();
    }

    @Override
    protected void onPause() {
        mPager.stopPlay();
        super.onPause();
    }


}

到此,基本上就完成了Viewpager的循环滑动和自动播放功能,还有一些小细节的东西没有加,如果说提示点什么的, 大家可以自行添加。

源码下载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值