Android banner轮播控件

最近工作用到了一个banner控件,所以写篇文章记录下,功能很简单

本文介绍用一种简单的方式实现一个banner轮播控件

最终效果

Android banner轮播控件_第1张图片

实现介绍

实现思路很简单,就是在viewpager的原始imageViewList的前后个各增加一个假数据。首先在原始数据的起始位置前面增加一个与最后一张图片一样的imageView,然后在原始数据最后增加一个与第一张原始数据相同的图片

这样,在最后一张图片向右切换时,滑动过程中漏出来的是假的第一张图片,当这张图片完全展示出来之后,在将整个viewpager定位到下标为1的真正的第一张图片。同理,在由第一张图片向左切换时,漏出的是假的最后一张图片,当这张图片完全展示后快速将viewpager快速定位到下标位5的图片。viewpager的index切换使用了mPager.setCurrentItem(pageIndex, false);这样用户肉眼无法看出来banner进行了切换

根据上面的思路需要在viewpager下标5->6切换、1->0切换的时候进行下标的特殊处理,这里主要结合了viewpager的onPageSelected回调和onPageScrollStateChanged回调

public void onPageSelected(int i) {
    pageIndex = i;//i取值从0~6
    final int imageViewSize = mImageViews.size();
    if (FAKE_ITEM_COUNT == 2 && imageViewSize > 1) {
        if (i == 0) {// 当视图在第一个时,将页面号设置为图片的最后一张
            pageIndex = imageViewSize - FAKE_ITEM_COUNT;
        } else if (i == mImageViews.size() - 1) {// 当视图在最后一个时,将页面号设置为图片的第一张
            pageIndex = 1;
        }
    }
}

其中FAKE_ITEM_COUNT是指假的2张图片,在onPageSelected计算好应该切换到的pageIndex后只需要在onPageScrollStateChanged中判断viewpager页面滑停后进行页面index设置即可

public void onPageScrollStateChanged(int i) {
    if (i == ViewPager.SCROLL_STATE_IDLE) {
        if (mPager.getCurrentItem() != pageIndex) {
            mPager.setCurrentItem(pageIndex, false);
        }
    }
}

实现轮播的方式是通过handler延迟一段时间发消息,而handler的消息处理中只要去设置当前index+1即可

int position = mPager.getCurrentItem() + 1;
if (position >= mPager.getAdapter().getCount()) { // 滑到底就再滑到开头
    position = 0;
}
mPager.setCurrentItem(position);

代码

整个bannerview的代码如下,其他的功能可以在此基础上加

public class BannerView extends FrameLayout implements ViewPager.OnPageChangeListener {
    private static final int MSG_AUTO_FLIP = 1001;
    private static final int AUTO_FLIP_INTERVAL = 5000;

    //多添加的2个item
    protected int FAKE_ITEM_COUNT = 0;

    protected List mImageViews = new ArrayList<>();
    protected ViewPager mPager;
    protected long mLastTouchUpTime;
    private int pageIndex;
    private Handler mHandler;

    public BannerView(Context context) {
        super(context);
        initView();
    }

    public BannerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initView();
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        startAutoFlip();
    }

    @Override
    public void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        stopAutoFlip();
    }


    private void initView() {
        setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT));

        mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case MSG_AUTO_FLIP:
                        autoFlip();
                        startAutoFlip();
                        break;

                    default:
                        break;
                }
            }
        };

        mPager = new MyPager(getContext());
        mPager.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT));
        mPager.setAdapter(new MyPagerAdapter());
        mPager.addOnPageChangeListener(this);

        addView(mPager, 0);
    }

    public void updateBannerView(ArrayList bannerViews, boolean isLoopable) {
        FAKE_ITEM_COUNT = isLoopable ? 2 : 0;

        if (bannerViews == null) {
            mImageViews.clear();
        } else {
            mImageViews = (ArrayList) bannerViews.clone();
        }

        mPager.getAdapter().notifyDataSetChanged();
        mPager.setCurrentItem(isLoopable && mImageViews.size() > 1 ? 1 : 0);
    }

    void autoFlip() {
        // 距离用户最近一次触摸松开的时间在自动滑动间隔之内
        if ((SystemClock.elapsedRealtime() - mLastTouchUpTime) < AUTO_FLIP_INTERVAL) {
            return;
        }

        int position = mPager.getCurrentItem() + 1;
        if (position >= mPager.getAdapter().getCount()) { // 滑到底就再滑到开头
            position = 0;
        }
        mPager.setCurrentItem(position);
    }

    public void startAutoFlip() {
        stopAutoFlip();
        if (mImageViews.size() < 2) {
            return;
        }

        mHandler.sendEmptyMessageDelayed(MSG_AUTO_FLIP, AUTO_FLIP_INTERVAL);
    }

    public void stopAutoFlip() {
        mHandler.removeMessages(MSG_AUTO_FLIP);
    }

    @Override
    public void onPageScrolled(int i, float v, int i1) {

    }

    @Override
    public void onPageSelected(int i) {
        pageIndex = i;
        final int imageViewSize = mImageViews.size();
        if (FAKE_ITEM_COUNT == 2 && imageViewSize > 1) {
            if (i == 0) {// 当视图在第一个时,将页面号设置为图片的最后一张
                pageIndex = imageViewSize - FAKE_ITEM_COUNT;
            } else if (i == mImageViews.size() - 1) {// 当视图在最后一个时,将页面号设置为图片的第一张
                pageIndex = 1;
            }
        }
    }

    @Override
    public void onPageScrollStateChanged(int i) {
        if (i == ViewPager.SCROLL_STATE_IDLE) {
            if (mPager.getCurrentItem() != pageIndex) {
                mPager.setCurrentItem(pageIndex, false);
            }
        }
    }

    public class MyPager extends ViewPager {
        private GestureDetector mGestureDetector;

        public MyPager(Context context) {
            this(context, null);
        }

        public MyPager(Context context, AttributeSet attrs) {
            super(context, attrs);

            mGestureDetector = new GestureDetector(context, new MyGestureListener());
            setFadingEdgeLength(0);
        }

        @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
            mLastTouchUpTime = SystemClock.elapsedRealtime();

            if (mGestureDetector.onTouchEvent(ev)) {
                getParent().requestDisallowInterceptTouchEvent(true);
            }
            return super.dispatchTouchEvent(ev);
        }

        class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
                if (Math.abs(distanceY) < Math.abs(distanceX)) {
                    return true;
                }
                return false;
            }
        }
    }

    class MyPagerAdapter extends PagerAdapter {

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

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

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

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            if (mImageViews.get(position).getParent() == null) {
                container.addView(mImageViews.get(position));
            }

            return mImageViews.get(position);
        }

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

下载

demo下载地址如下,感兴趣的可以看下~

https://download.csdn.net/download/u010420435/10643548

你可能感兴趣的:(Android笔记)