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};去掉