Android基础控件——Banner轮播图的无限循环轮播功能、手动滑动功能

Banner轮播图的无限循环轮播功能、手动滑动功能


轮播图实现:(假如5张图轮播)

1、在List中存好这5张图,传到ViewPager的Adapter中,相当于5张图片横铺在ViewPager控件中。

2、设置ViewPager一开始的起始位置为5*1000=5000,并用seletedBanner记录该位置。

3、在PagerAdapter中将其getCount方法返回Integer的最大值,让它向左向右滑都不会越界。

4、在PagerAdapter中必须对当前位置%5(由于5张图,%5结果在0-4之间,刚好是图片集合的下标,如5002%5=2,就是List[2]中的对象)

5、ViewPager监听滚动事件,用seletedBanner记录新位置。

6、在onResume中开始轮播。

圆点实现:

1、在一个水平的布局中添加5个圆点View对象,并存入一个List中。

2、遍历圆点List,在ViewPager滚动回调中判断seletedBanner(当前位置)%5,则该得到的值为选中圆点,其他为未选中圆点。

其效果图:



实现步骤


1、自定义RelativeLayout,编写固定的构造方法

public class MyBannerView extends RelativeLayout implements View.OnTouchListener, ViewPager.OnPageChangeListener {

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

    public MyBannerView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyBannerView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //初始化工作
        initBannerViews(context, attrs, defStyleAttr);
    }
}

 

2、声明需要用到的变量

    //轮播图控件
    private ViewPager targetVp;
    //轮播图集合
    private ArrayList<View> bannerList;
    //指示器图集合
    private ArrayList<View> indicationList;
    //上下文
    private Context context;
    //当前轮播图位置
    private int selectedBanner;
    //提示轮播
    private final static int BANNER_CHANGE = 0;
    //是否为网络图片加载,作用是:如果是网络图片加载就不滚动轮播图,让用户自己手动滑动轮播图
    boolean isNetImg = false;


3、初始化用到的组件

    private void initBannerViews(Context context, AttributeSet attrs, int defStyleAttr) {
        this.context = context;
        //初始化ViewPager
        targetVp = new ViewPager(context);
        targetVp.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        targetVp.setOnTouchListener(this);
        targetVp.setOnPageChangeListener(this);
        //添加到View中
        addView(targetVp);
    }

4、提供方法加载图片和指示器


这里有两个方法,加载本地图片和加载网络图片,加载网络图片用到Glide第三方框架,Glide的学习可以查看我的博客

    /**
     * 在本地Drawable中加载轮播图
     *
     * @param activity
     * @param img_urls 轮播图drawable的ID
     */
    public void initShowImageForLocal(Activity activity, int[] img_urls) {
        //指示器布局
        LinearLayout ly_indication = new LinearLayout(activity);
        LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        //指示器边距
        params.bottomMargin = 15;
        //指示器位置
        params.addRule(ALIGN_PARENT_BOTTOM);
        params.addRule(CENTER_HORIZONTAL);
        //添加到View中
        addView(ly_indication, params);
        //图片集合和指示器集合
        bannerList = new ArrayList<View>();
        indicationList = new ArrayList<View>();
        for (int i = 0; i < img_urls.length; i++) {
            //初始化图片
            ImageView iv = new ImageView(activity);
            iv.setScaleType(ImageView.ScaleType.FIT_XY);
            iv.setBackgroundResource(img_urls[i]);
            bannerList.add(iv);
            //初始化指示器
            ImageView iv2 = new ImageView(activity);
            LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
            lp.setMargins(8, 0, 0, 0);
            iv2.setLayoutParams(lp);
            //初始化指示器默认为第一张高亮
            if (i == 0) {
                iv2.setBackgroundResource(R.drawable.home_top_ic_point_on);
            } else {
                iv2.setBackgroundResource(R.drawable.home_top_ic_point_off);
            }
            indicationList.add(iv2);
            //添加到圆点布局
            ly_indication.addView(iv2);
        }
        //初始化轮播Adapter
        HomeBannerAdapter bannerAdapter = new HomeBannerAdapter(bannerList, activity);
        targetVp.setAdapter(bannerAdapter);
        //初始化当前位置
        targetVp.setCurrentItem(bannerList.size() * 1000);
        //当前position
        selectedBanner = bannerList.size() * 1000;
    }

    /**
     * 通过网络Url加载轮播图
     *
     * @param activity
     * @param img_urls 网络图片的URL
     */
    public void initShowImageForNet(Activity activity, List<String> img_urls) {
        //标识是网络加载
        isNetImg = true;
        //指示器布局
        LinearLayout ly_indication = new LinearLayout(activity);
        LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        // 指示器边距
        params.bottomMargin = 15;
        //指示器位置
        params.addRule(ALIGN_PARENT_BOTTOM);
        params.addRule(CENTER_HORIZONTAL);
        //添加到View中
        addView(ly_indication, params);
        //图片集合和指示器集合
        bannerList = new ArrayList<View>();
        indicationList = new ArrayList<View>();
        for (int i = 0; i < img_urls.size(); i++) {
            //初始化图片
            ImageView iv = new ImageView(activity);
            iv.setScaleType(ImageView.ScaleType.FIT_XY);
            GlideUtils.setImageView(context, img_urls.get(i), iv);
            bannerList.add(iv);
            //初始化指示器
            ImageView iv2 = new ImageView(activity);
            LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
            lp.setMargins(8, 0, 0, 0);
            iv2.setLayoutParams(lp);
            if (i == 0) {
                iv2.setBackgroundResource(R.drawable.home_top_ic_point_on);
            } else {
                iv2.setBackgroundResource(R.drawable.home_top_ic_point_off);
            }
            indicationList.add(iv2);
            //添加到圆点布局
            ly_indication.addView(iv2);
        }
        //初始化轮播数据
        HomeBannerAdapter bannerAdapter = new HomeBannerAdapter(bannerList, activity);
        targetVp.setAdapter(bannerAdapter);
        //初始化当前位置
        targetVp.setCurrentItem(bannerList.size() * 1000);
        //当前position
        selectedBanner = bannerList.size() * 1000;
    }


5、实现监听事件

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {
        //改变当前位置指针
        selectedBanner = position;
        //改变指示器变化
        bannerPointLight(position % indicationList.size());
    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }


    @Override
    public boolean onTouch(View v, MotionEvent event) {
        //如果是网络加载则没必要监听
        if (isNetImg) {
            return false;
        }
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //结束轮播
                mHandler.removeCallbacksAndMessages(null);
                break;
            case MotionEvent.ACTION_UP:
                //开启轮播
                mHandler.sendEmptyMessageDelayed(BANNER_CHANGE, 3000);
                break;
            case MotionEvent.ACTION_CANCEL:
                //开启轮播
                mHandler.sendEmptyMessageDelayed(BANNER_CHANGE, 3000);
                break;
        }
        return false;
    }


6、提供开启轮播和结束轮播的方法

    /**
     * 开始轮播
     */
    public void startBanner() {
        //开启轮播
        mHandler.sendEmptyMessageDelayed(BANNER_CHANGE, 3000);
    }

    /**
     * 结束轮播
     */
    public void endBanner() {
        //结束轮播
        mHandler.removeCallbacksAndMessages(null);
    }


7、处理轮播

    /**
     * 消息处理器
     */
    private Handler mHandler = new Handler() {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case BANNER_CHANGE:
                    //形成轮播循环
                    targetVp.setCurrentItem(selectedBanner + 1);
                    mHandler.sendEmptyMessageDelayed(BANNER_CHANGE, 3000);
                    break;
            }
        }
    };


8、编写HomeBannerAdapter

    /**
     * 适配器
     */
    public class HomeBannerAdapter extends PagerAdapter {

        private List<View> views;
        private Context context;

        public HomeBannerAdapter(List<View> views, Context context) {
            this.context = context;
            this.views = views;
        }

        public Object instantiateItem(View container, int position) {
            final int currentItem = position % views.size();
            ((ViewPager) container).addView(views.get(currentItem));
            return views.get(currentItem);
        }

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

        public int getCount() {
            return Integer.MAX_VALUE;
        }

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


9、编写两个圆点的xml文件


① 红点

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">

    <solid android:color="#FF5000"/>

    <stroke
        android:width="0.1dp"
        android:color="#8888" />
    <size
        android:width="6dp"
        android:height="6dp" />
</shape>


② 灰点

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">

    <solid android:color="#88ffffff"/>

    <stroke
        android:width="0.1dp"
        android:color="#8888" />
    <size
        android:width="6dp"
        android:height="6dp" />
</shape>

10、接着就可以在Acitivity中使用我们的自定义的BannerView


① 编写布局文件,使用我们的自定义BannerView

        <com.handsome.didi.View.MyBannerView
                android:id="@+id/vp_banner"
                android:layout_width="match_parent"
                android:layout_height="120dp" />


② 在代码中找到对应ID控件,并且初始化

vp_banner = findView(R.id.vp_banner);
vp_banner.initShowImageForNet(getActivity(), new ArrayList<String>{"","","",""});


③ 开启轮播和停止轮播

    @Override
    public void onResume() {
        super.onResume();
        //开始轮播
        vp_banner.startBanner();
    }

    @Override
    public void onPause() {
        super.onPause();
        //停止轮播
        vp_banner.endBanner();
    }

源码下载


源码下载说明

1、网络图片加载要用到第三库Glide

2、网络加载默认是不会自动轮播的,如果需要自动轮播需要将if(isNetImg){return false};去掉







  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

许英俊潇洒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值