一款好用的banner轮播图控件

本文介绍了一款好用的轮播图控件Banner,支持多种效果且调用简便。文章详细讲解了如何在项目中引入并使用该控件,并深入分析了其实现无限轮播的原理。

banner轮播图控件介绍

我们在日常开发过程中经常会碰到轮播图的需求,一般来说都是自己用ViewPager实现的,但是这种实现过程没有经过封装,日常调用起来也比较繁琐,有着各式各样的问题,因此我在github上找到一款非常好用的开源轮播图控件banner,调用起来非常方便,还支持各种效果,部分效果如下图所示。使用时的版本是1.4.9。

1
2

基本使用

要使用这个控件,首先我们需要在module的build.gradle中添加依赖

dependencies{
    compile 'com.youth.banner:banner:1.4.9'
}

如果要使用网络图片或本地图片要需要在AndroidManifest.xml添加权限

<!-- if you want to load images from the internet -->
<uses-permission android:name="android.permission.INTERNET" /> 

<!-- if you want to load images from a file OR from the internet -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

接下来就可以使用了

最简单的使用方法是在activity或fragment布局文件中

<com.youth.banner.Banner
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/banner"
    android:layout_width="match_parent"
    android:layout_height="高度自己设置" />

或者自己new出来控件。

设置图片加载器继承ImageLoader

public class GlideImageLoader extends ImageLoader {
    @Override
    public void displayImage(Context context, Object path, ImageView imageView) {
        /**
          注意:
          1.图片加载器由自己选择,这里不限制,只是提供几种使用方法
          2.返回的图片路径为Object类型,由于不能确定你到底使用的那种图片加载器,
          传输的到的是什么格式,那么这种就使用Object接收和返回,你只需要强转成你传输的类型就行,
          切记不要胡乱强转!
         */
        eg:

        //Glide 加载图片简单用法
        Glide.with(context).load(path).into(imageView);

        //Picasso 加载图片简单用法
        Picasso.with(context).load(path).into(imageView);

        //用fresco加载图片简单用法,记得要写下面的createImageView方法
        Uri uri = Uri.parse((String) path);
        imageView.setImageURI(uri);
    }

    //提供createImageView 方法,如果不用可以不重写这个方法,主要是方便自定义ImageView的创建
    @Override
    public ImageView createImageView(Context context) {
        //使用fresco,需要创建它提供的ImageView,当然你也可以用自己自定义的具有图片加载功能的ImageView
        SimpleDraweeView simpleDraweeView=new SimpleDraweeView(context);
        return simpleDraweeView;
    }
}

最后,在Activity或者Fragment中配置Banner

banner.setImages(image)
        .setImageLoader(new GlideImageLoader())
        .setOnBannerListener(this)
        .start();

就可以播放出轮播图了,该控件还有很多方法可以设置样式,切换动画等属性,具体可以参考项目主页https://github.com/youth5201314/banner

实现源码分析

知其然还要知其所以然,我们用了这个控件还要知道这个控件是怎么实现的。

首先我们从Banner类切入,因为它是轮播图的实现控件

从源码中可以看到,Banner类继承FrameLayout,然后在它的构造函数中inflate了banner.xml,这个布局的结构如下:

<RelativeLayout
    android:clipChildren="false">
    <!--轮播图-->
    <ViewPager
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    <!--底部布局,包括指示器,title,页码等-->
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true">
        ......
    </RelativeLayout>
</RelativeLayout>

同时,在初始化函数中,还初始化了自定义属性等。

接下来我们要关注的就是这个控件是如何实现无限轮播的

可以看到在Activity中通过

banner.setImages(image)
        .setImageLoader(new GlideImageLoader())
        .setOnBannerListener(this)
        .start();

开启轮播,setImages()方法设置了轮播图的图片路径,配合ImageLoader加载图片,继承ImageLoader抽象类并重写displayImage方法来具体实现图片的加载逻辑,setOnBannerListener()方法设置banner的点击事件,start()方法开始轮播。

我们具体看一下start()

public Banner start() {
    setBannerStyleUI(); //设置ui
    setImageList(imageUrls); //初始化ImageViews
    setData(); //初始化ViewPager并开始播放
    return this;
}
setBannerStyleUI()

第一个函数setBannerStyleUI()用于设置UI显示的,包括指示器样式,标题样式等等。

setImageList(imageUrls)

第二个函数是我们关注的重点,在这个方法中我们通过setImages()方法获取到的对象List,来初始化轮播图显示的ImageView,这里用了一个技巧来实现无限轮播:ImageView数量比图片数量大2,imageViews.get(0)为最后一张图片,imageViews.get(size-1)为第一张图片

if (i == 0) {
    url = imagesUrl.get(count - 1);
} else if (i == count + 1) {
    url = imagesUrl.get(0);
} else {
    url = imagesUrl.get(i - 1);
}

这样在滑动到第一张或者最后一张后,接下来的一张图片是最后一张或者第一张,同时在onPageScrollStateChanged中检测,在停止滑动的状态下如果是最后一个ImageView或者第0个ImageView则更新ViewPager状态,利用viewPager.setCurrentItem()方法设置其状态为最后一张或者第一张,这样就平滑过度了。

@Override
public void onPageScrollStateChanged(int state) {
    if (mOnPageChangeListener != null) {
        mOnPageChangeListener.onPageScrollStateChanged(state);
    }
    currentItem = viewPager.getCurrentItem();
    switch (state) {
        case 0://No operation
            if (currentItem == 0) {
                viewPager.setCurrentItem(count, false);
            } else if (currentItem == count + 1) {
                viewPager.setCurrentItem(1, false);
            }
            break;
        case 1://start Sliding 正在滑动
            if (currentItem == count + 1) {
                viewPager.setCurrentItem(1, false);
            } else if (currentItem == 0) {
                viewPager.setCurrentItem(count, false);
            }
            break;
        case 2://end Sliding
            break;
    }
}
setData()

setData()方法中初始化了ViewPager,如果开启了自动轮播,会调用startAutoPlay()方法利用handler.postDelayed去自动切换ViewPager。

这里额外提一下设置切换动画,是利用viewPager.setPageTransformer()方法进行设置,这里作者给我们提供了很多动画的默认实现,如果没有需要的切换动画效果,就需要自己去实现PagerTransformer接口去实现自己想要的切换动画,关于切换动画和clipChildren属性,这篇文章介绍的很透彻http://blog.youkuaiyun.com/u012702547/article/details/52334161

public Banner setPageTransformer(boolean reverseDrawingOrder, PageTransformer transformer) {
    viewPager.setPageTransformer(reverseDrawingOrder, transformer);
    return this;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值