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

2023-03-28 16:15:41

在做这个效果的时候,我第一时间看了网上的轮播方式,发现问题很多,有的人在代码里大量的判断手动滑动和自动滑动的状态改变,有的人的轮播是定义了一个很大的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

  • 作者:月色下的独轮车
  • 原文链接:https://blog.csdn.net/baidu_31093133/article/details/51789913
    更新时间:2023-03-28 16:15:41