viewpager轮播图的实现(简洁易懂)

来源:互联网 发布:热敏标签打印软件 编辑:程序博客网 时间:2024/04/30 06:53

在做这个效果的时候,我第一时间看了网上的轮播方式,发现问题很多,有的人在代码里大量的判断手动滑动和自动滑动的状态改变,有的人的轮播是定义了一个很大的Int值,通过顺序播放相同的图片来实现的伪轮播,看过这些代码感觉并不满意,所以尝试自己实现。

在轮播更新UI的时候,我尝试了Thread+handler,handler.postdelay,和timer+timertask+handler的方式,前两种方式都会出现一些小Bug,并且不利于功能扩展,读者可自行尝试,所以我采用了第三种方式。

在解决手动滑动和自动滑动的上,其实根本不用设置什么标志位进行大量的判断,这是一个思维误区,因为我们根本不需要解决这两者之间的冲突,我们只需要关注当前页面是不是改变成功了,当前页面是第几个就可以了。所以我们只需要判断onPageScrollStateChanged的state为2的时候,这个页面的position就可以解决上述问题。

如果要给自己的轮播增加一些文字描述也非常的简单,具体可以看我下面的代码分析。

效果图:
轮播图
直接看核心代码:

MainActivity.java

public class MainActivity extends AppCompatActivity {    private Context ctx;    //viewpager初始化    private ViewPager viewPager;    private List<View> list;    private LPagerAdapter adapter;    //轮播控制    private Handler handler;    private Timer timer;    private TimerTask task;    private int mPosition;    //轮播内容    private LinearLayout point_container;    private ImageView[] imgs;    private List<ImageTip> tips;    private TextView tip1;    private TextView tip2;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        viewPager = (ViewPager) findViewById(R.id.viewpager);        tip1 = (TextView) findViewById(R.id.tv_tip1);        tip2 = (TextView) findViewById(R.id.tv_tip2);        ctx = this;        initdata();        initpoint();        initTip();        //自定义adapter        adapter = new LPagerAdapter(ctx, list, new LPagerImgClickListener() {            @Override            public void ImgClick(int position) {                Toast.makeText(ctx, "点击了" + mPosition, Toast.LENGTH_SHORT).show();                Intent intent = new Intent(ctx, SecondActivity.class);                intent.putExtra("position", position);                startActivity(intent);            }        });        //第一种动画//        viewPager.setPageTransformer(true, new ZoomOutPageTransformer());        //第二种动画        viewPager.setPageTransformer(true,new DepthPageTransformer());        viewPager.setAdapter(adapter);        //监听页面的改变        viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {            @Override            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {//                Log.i("LHD", "onPageScrolled" + "  positionOffset:" + positionOffset + "  positionOffsetPixels:" + positionOffsetPixels);            }            @Override            public void onPageSelected(final int position) {//                Log.i("LHD", "onPageSelected" + position);            }            @Override            public void onPageScrollStateChanged(int state) {//                Log.i("LHD", "onPageScrollStateChanged:" + state);                if (state == 2) {//图片切换成功的状态为2                    mPosition = viewPager.getCurrentItem();                    Log.i("LHD", "当前页是:" + mPosition);                    for (int i = 0; i < list.size(); i++) {//设置所有原点                        imgs[i].setImageResource(R.drawable.point1);                    } //设置当前页的小圆点图片和文字信息            imgs[mPosition].setImageResource(R.drawable.point2);                    tip1.setText(tips.get(mPosition).getTip1());                    tip2.setText(tips.get(mPosition).getTip2());                }            }        });        imgPlay();    }    private void imgPlay() {        //循环播放        task = new TimerTask() {            @Override            public void run() {                Message msg = new Message();                msg.what = 1;                handler.sendMessage(msg);            }        };        timer = new Timer();        timer.schedule(task, 3000, 3000);        handler = new Handler() {            @Override            public void handleMessage(Message msg) {                if (msg.what == 1) {                    if (mPosition == (list.size() - 1)) {                        viewPager.setCurrentItem(0, true);                    } else {                        Log.i("LHD", "bbbb:   " + mPosition + "当前的进程ID:  " + Thread.currentThread().getId());                        viewPager.setCurrentItem(mPosition + 1, true);                        Log.i("LHD", "cccc:   " + mPosition);                    }                }            }        };    }    private void imgStop() {        handler.removeMessages(1);        timer.cancel();        task.cancel();    }    private void initdata() {        list = new ArrayList<View>();        ImageView iv = new ImageView(ctx);        ImageView iv2 = new ImageView(ctx);        ImageView iv3 = new ImageView(ctx);        ImageView iv4 = new ImageView(ctx);        ImageView iv5 = new ImageView(ctx);        ImageView iv6 = new ImageView(ctx);        iv.setImageResource(R.drawable.image3);        iv2.setImageResource(R.drawable.image4);        iv3.setImageResource(R.drawable.image5);        iv4.setImageResource(R.drawable.image6);        iv5.setImageResource(R.drawable.image7);        iv6.setImageResource(R.drawable.image8);        list.add(iv);        list.add(iv2);        list.add(iv3);        list.add(iv4);        list.add(iv5);        list.add(iv6);        imgs = new ImageView[list.size()];    }    private void initpoint() {        point_container = (LinearLayout) findViewById(R.id.point_container);        for (int i = 0; i < list.size(); i++) {            ImageView imageView = new ImageView(ctx);            imageView.setImageResource(R.drawable.point1);            //对布局控件添加相对属性            LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(                    20,                    20);            //添加规则,示例 靠父控件最右边            param.setMargins(10, 0, 0, 0);            Log.i("LHD", "添加小圆点:" + list.size());            imgs[i] = imageView;//添加到图片数组            point_container.addView(imageView, param);            imgs[0].setImageResource(R.drawable.point2);        }    }    private void initTip() {        tips = new ArrayList<ImageTip>();        tips.add(new ImageTip("山治:我要寻找all bule", "2016/6/23"));        tips.add(new ImageTip("弗兰奇:我要飞上天", "2016/6/24"));        tips.add(new ImageTip("乌索普:我要成为勇敢的海上战士", "2016/6/25"));        tips.add(new ImageTip("罗宾:我要寻找历史原文", "2016/6/26"));        tips.add(new ImageTip("娜美:我要环绕世界一周", "2016/6/27"));        tips.add(new ImageTip("路飞:我要成为海贼王!", "2016/6/28"));        tip1.setText(tips.get(0).getTip1());        tip2.setText(tips.get(0).getTip2());    }    @Override    protected void onPause() {        super.onPause();        Log.i("LHD", "onPause");        //保存当前页位置        mPosition = viewPager.getCurrentItem();        //停止轮播        imgStop();    }    @Override    protected void onRestart() {        super.onRestart();        Log.i("LHD", "onRestart");        //重新启动轮播        imgPlay();    }}

分析:

imgPlay()
这个函数就是用来控制图片轮播的函数,
在这个函数里,使用了Timer+TimerTask+handler的方式来更新UI。
imgStop()
这个函数用来取消图片轮播,当按下HOME键或者返回键的时候需要将动画取消,再次启动Activity的时候再恢复。
initdata()
将需要轮播的图片存放在一个List里,并且定义了一个存放图片的数组。
initpoint()
根据图片数量来添加小圆点
initTip()
图片下面文字的初始化
重写了onPause方法和onRestart方法,在onPause方法里保存图片位置,停止动画,在onRestart方法里重启动画。

接下来看ViewPager的适配器:
LPagerAdapter.java

/** * Created by LHD on 2016/6/29. */public class LPagerAdapter extends PagerAdapter {    private Context ctx;    private List<View> mlist;    private LPagerImgClickListener mlistener;    public LPagerAdapter(Context ctx, List<View> mlist, LPagerImgClickListener listener) {        this.ctx = ctx;        this.mlist = mlist;        this.mlistener = listener;    }    @Override    public int getCount() {        return mlist.size();    }    @Override    public boolean isViewFromObject(View view, Object object) {        return view == object;    }    @Override    public Object instantiateItem(ViewGroup container, final int position) {        container.addView(mlist.get(position));        mlist.get(position).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {//                Toast.makeText(ctx, "点击了" + position, Toast.LENGTH_SHORT).show();                if (mlistener != null) {                    mlistener.ImgClick(position);                }            }        });        return mlist.get(position);    }    @Override    public void destroyItem(ViewGroup container, int position, Object object) {        container.removeView(mlist.get(position));    }}

和普通的viewpager适配器没有区别,只是增加了一个监听,当点击图片的时候,调用mlistener.ImgClick(position);

接口:
LPagerImgClickListener.java

public interface LPagerImgClickListener {    public void ImgClick(int position);}

另外提供了两种viewpager的动画,这两种动画都是谷歌官方提供,可以根据需要修改里面的参数。

动画1:
DepthPageTransformer.java

/** * Created by LHD on 2016/6/30. */public class DepthPageTransformer implements ViewPager.PageTransformer{    private static float MIN_SCALE = 0.75f;    @SuppressLint("NewApi")    @Override    public void transformPage(View view, float position) {        int pageWidth = view.getWidth();        if (position < -1) { // [-Infinity,-1)            // This page is way off-screen to the left.            view.setAlpha(0);        } else if (position <= 0) { // [-1,0]            // Use the default slide transition when            // moving to the left page            view.setAlpha(1);            view.setTranslationX(0);            view.setScaleX(1);            view.setScaleY(1);        } else if (position <= 1) { // (0,1]            // Fade the page out.            view.setAlpha(1 - position);            // Counteract the default slide transition            view.setTranslationX(pageWidth * -position);            // Scale the page down (between MIN_SCALE and 1)            float scaleFactor = MIN_SCALE + (1 - MIN_SCALE)                    * (1 - Math.abs(position));            view.setScaleX(scaleFactor);            view.setScaleY(scaleFactor);        } else { // (1,+Infinity]            // This page is way off-screen to the right.            view.setAlpha(0);        }    }}

动画2:
ZoomOutPageTransformer.java

package com.example.eventbus.imagecarousellhd;import android.support.v4.view.ViewPager;import android.view.View;/** * Created by LHD on 2016/6/30. */public class ZoomOutPageTransformer implements ViewPager.PageTransformer{    private static float MIN_SCALE = 0.85f;    private static float MIN_ALPHA = 0.5f;    @Override    public void transformPage(View view, float position) {        int pageWidth = view.getWidth();        int pageHeight = view.getHeight();        if (position < -1) { // [-Infinity,-1)            // This page is way off-screen to the left.            view.setAlpha(0);        } else if (position <= 1) { // [-1,1]            // Modify the default slide transition to            // shrink the page as well            float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));            float vertMargin = pageHeight * (1 - scaleFactor) / 2;            float horzMargin = pageWidth * (1 - scaleFactor) / 2;            if (position < 0) {                view.setTranslationX(horzMargin - vertMargin / 2);            } else {                view.setTranslationX(-horzMargin + vertMargin / 2);            }            // Scale the page down (between MIN_SCALE and 1)            view.setScaleX(scaleFactor);            view.setScaleY(scaleFactor);            // Fade the page relative to its size.            view.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE)                    / (1 - MIN_SCALE) * (1 - MIN_ALPHA));        } else { // (1,+Infinity]            // This page is way off-screen to the right.            view.setAlpha(0);        }    }}

代码下载:
http://dl.download.csdn.net/down11/20160630/0d6a1d49d94dc37ad2d036876956b959.zip?response-content-disposition=attachment%3Bfilename%3D%22ImageCarouselLHD.zip%22&OSSAccessKeyId=9q6nvzoJGowBj4q1&Expires=1467270036&Signature=9MhZGsUC9qiLVG7y2YSWjj1EbIo%3D

1 0
原创粉丝点击