一款好用的banner輪播圖控制元件
banner輪播圖控制元件介紹
我們在日常開發過程中經常會碰到輪播圖的需求,一般來說都是自己用ViewPager實現的,但是這種實現過程沒有經過封裝,日常呼叫起來也比較繁瑣,有著各式各樣的問題,因此我在github上找到一款非常好用的開源輪播圖控制元件banner,呼叫起來非常方便,還支援各種效果,部分效果如下圖所示。使用時的版本是1.4.9。
基本使用
要使用這個控制元件,首先我們需要在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();
實現原始碼分析
知其然還要知其所以然,我們用了這個控制元件還要知道這個控制元件是怎麼實現的。
首先我們從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.csdn.net/u012702547/article/details/52334161
public Banner setPageTransformer(boolean reverseDrawingOrder, PageTransformer transformer) {
viewPager.setPageTransformer(reverseDrawingOrder, transformer);
return this;
}