Android使用ViewPager实现无限循环banner图,实现手指滑动时轮播停止功能

先看效果图

banner图示例

可实现自动轮播以及手动左右无限滑动

实现的原理是在自己的准备的banner图的首尾再加上两张图,中间的adcde是我们需要轮播的图片,首尾则为特意加上去的,目的是使滑动更加的平滑,并不参与实际的操作。

当页面从编号1滑动到0时,将页面设置为5;

当页面从编号5滑动到6时,将页面设置为1;.

为了防止页面停顿,突然跳到下一页的情况,将设置页面的代码放到finishUpdate(@NonNull ViewGroup container)方法中去实现,该方法会在view创建和销毁之前调用。

具体实现如下:

布局文件代码:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <android.support.v4.view.ViewPager
        android:id="@+id/vp_banner"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <RadioGroup
        android:id="@+id/rg_indicator"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingBottom="2dp"
        android:orientation="horizontal"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true" />

</RelativeLayout>

自定义视图BannerPager

public class BannerPager extends RelativeLayout implements View.OnClickListener {

    private static final String TAG = "BannerPager";
    private Context mContext; // 声明一个上下文对象
    private ViewPager vp_banner; // 声明一个翻页视图对象
    private RadioGroup rg_indicator; // 声明一个单选组对象
    private List<ImageView> mViewList = new ArrayList<ImageView>(); // 声明一个图像视图队列
    private int mInterval = 2000; // 轮播的时间间隔,单位毫秒

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

    public BannerPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        initView();
    }

    // 初始化视图
    private void initView() {
        // 根据布局文件banner_pager.xml生成视图对象
        View view = LayoutInflater.from(mContext).inflate(R.layout.banner_pager, null);
        // 从布局文件中获取名叫vp_banner的翻页视图
        vp_banner = view.findViewById(R.id.vp_banner);
        // 从布局文件中获取名叫rg_indicator的单选组
        rg_indicator = view.findViewById(R.id.rg_indicator);
        addView(view); // 将该布局视图添加到横幅轮播条
    }

    // 开始广告轮播
    public void start() {
        // 延迟若干秒后启动滚动任务
        mHandler.postDelayed(mScroll, mInterval);
    }

    // 停止广告轮播
    public void stop() {
        // 移除滚动任务
        mHandler.removeCallbacks(mScroll);
    }

    // 设置广告轮播的时间间隔
    public void setInterval(int interval) {
        mInterval = interval;
    }

    // 设置广告图片队列
    public void setImage(ArrayList<Integer> imageList) {
        int dip_15 = Utils.dip2px(mContext, 15);
        // 根据图片队列生成图像视图队列
        for (int i = 0; i < imageList.size(); i++) {
            Integer imageID = imageList.get(i);
            ImageView iv = new ImageView(mContext);
            iv.setLayoutParams(new LayoutParams(
                    LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
            iv.setScaleType(ImageView.ScaleType.FIT_XY);
            iv.setImageResource(imageID);
            iv.setOnClickListener(this);
            mViewList.add(iv);
        }
        // 设置翻页视图的图像翻页适配器
        vp_banner.setAdapter(new ImageAdapater());
        // 给翻页视图添加简单的页面变更监听器
        vp_banner.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            int currentPosition = 1;

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

            }

            @Override
            public void onPageSelected(int position) {
                if (position == mViewList.size() - 1) {
                    // 设置当前值为1
                    currentPosition = 1;
                } else if (position == 0) {
                    // 如果索引值为0了,就设置索引值为倒数第二个
                    currentPosition = mViewList.size() - 2;
                } else {
                    currentPosition = position;
                }
                setButton(currentPosition);
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
        // 根据图片队列生成指示按钮队列
        for (int i = 0; i < imageList.size(); i++) {
            RadioButton radio = new RadioButton(mContext);
            radio.setLayoutParams(new RadioGroup.LayoutParams(dip_15, dip_15));
            radio.setGravity(Gravity.CENTER);
            radio.setButtonDrawable(R.drawable.indicator_selector);
            rg_indicator.addView(radio);
//            如果是第一或者最后一张图,隐藏指示按钮
            if (i == 0 || i == imageList.size() - 1) {
                Bitmap a = null;
                radio.setButtonDrawable(new BitmapDrawable(a));
            }
        }
        // 设置翻页视图默认显示第一页
        vp_banner.setCurrentItem(1);
        // 默认高亮显示第一个指示按钮
        setButton(1);
    }

    // 设置选中单选组内部的哪个单选按钮
    private void setButton(int position) {
        ((RadioButton) rg_indicator.getChildAt(position)).setChecked(true);
    }

    private Handler mHandler = new Handler(); // 声明一个处理器对象
    // 定义一个滚动任务
    private Runnable mScroll = new Runnable() {
        @Override
        public void run() {
            scrollToNext(); // 滚动广告图片
            // 延迟若干秒后继续启动滚动任务
            mHandler.postDelayed(this, mInterval);
        }
    };

    // 滚动到下一张广告图
    public void scrollToNext() {
        // 获得下一张广告图的位置
        int index = vp_banner.getCurrentItem() + 1;
        if (index >= mViewList.size() - 1) {
            index = 1;
        }
        // 设置翻页视图显示指定位置的页面
        vp_banner.setCurrentItem(index);
    }

    // 定义一个图像翻页适配器
    private class ImageAdapater extends PagerAdapter {

        // 获取页面项的个数
        public int getCount() {
            return mViewList.size();
        }

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

        // 从容器中销毁指定位置的页面
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView(mViewList.get(position));
        }

        //无论是创建view添加到容器中  还是 销毁view 都是在此方法结束之后执行的
        @Override
        public void finishUpdate(@NonNull ViewGroup container) {
            super.finishUpdate(container);
            int position = vp_banner.getCurrentItem();

            if (position == 0) {
                position = mViewList.size() - 2;
                vp_banner.setCurrentItem(position, false);
            } else if (position == mViewList.size() - 1) {
                position = 1;
                vp_banner.setCurrentItem(position, false);
            }
        }

        // 实例化指定位置的页面,并将其添加到容器中
        public Object instantiateItem(ViewGroup container, int position) {
            container.addView(mViewList.get(position));
            return mViewList.get(position);
        }


    }

    @Override
    public void onClick(View v) {
        // 获取翻页视图当前页面项的序号
        int position = vp_banner.getCurrentItem();
        // 触发点击监听器的onBannerClick方法
        mListener.onBannerClick(position);
    }

    // 设置广告图的点击监听器
    public void setOnBannerListener(BannerClickListener listener) {
        mListener = listener;
    }

    // 声明一个广告图点击的监听器对象
    private BannerClickListener mListener;

    // 定义一个广告图片的点击监听器接口
    public interface BannerClickListener {
        void onBannerClick(int position);
    }
}

activity代码:

    private void init() {
        // 获取横幅轮播条的布局参数
        ViewGroup.LayoutParams params = mbannerPager.getLayoutParams();
        params.height = (int) (Utils.getScreenWidth(getActivity()) * 250f / 640f);
        // 设置横幅轮播条的布局参数
        mbannerPager.setLayoutParams(params);
        // 设置横幅轮播条的广告图片队列
        mbannerPager.setImage(ImageList.getDefault());
        // 设置横幅轮播条的广告点击监听器
        mbannerPager.setOnBannerListener(this);
        // 开始广告图片的轮播滚动
        mbannerPager.start();
    }

上面为最初的代码,大体功能都已实现,现补充手指滑动时轮播停止功能,只需在自定义试图中为ViewPager加上手势触摸监听器即可!在手指滑动时停止轮播,抬起时开启轮播!

        vp_banner.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_MOVE:
                        stop();
                        break;
                    case MotionEvent.ACTION_UP:
                        start();
                        break;
                    default:
                        break;
                }
                return false;
            }
        });

源码地址://download.csdn.net/download/qq_41824185/12017775

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值