android 圖片輪播(自動迴圈輪播)
阿新 • • 發佈:2019-02-11
實現思路就是通過viewPager自定義元件,支援圖片點選、手動滑動、自動輪播、初始化定位位置。不廢話了先上圖
元件使用
到此通過元件就可以實現上圖的效果了。繼續向下看,自定義view內部的內容。 自定義View一共用了三個檔案。public class BannerAutoActivity extends Activity { BannerLayout bannerLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_banner_auto); initView(); } private void initView(){ //介面初始化view bannerLayout = (BannerLayout) findViewById(R.id.bannerLayout); //組織介面圖片資料 List<ImageView> ivList = new ArrayList<>(); for(int i=0;i<6;i++){ ImageView imageView = new ImageView(this); ViewGroup.LayoutParams layoutParams = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT); imageView.setLayoutParams(layoutParams); imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); imageView.setImageResource(R.mipmap.banner_01+i); ivList.add(imageView); } //設定初始展示第幾張 // bannerLayout.setIdx(0); bannerLayout.startBanner(ivList,R.drawable.point_background); //圖片點選事件監聽 bannerLayout.setonClickImg(new BannerLayout.onClickImg() { @Override public void ItemId(int id) { int temp = id+1; Toast.makeText(BannerAutoActivity.this,"這是第"+temp+"張圖",Toast.LENGTH_SHORT).show(); } }); } }
Banners.java
ChildViewPager.java
BannerLayout.java
實體類
Banners.java
public class Banners { private String picurl; private String url; private String name; public void setPicurl(String picurl) { this.picurl = picurl; } public String getPicurl() { return this.picurl; } public void setUrl(String url) { this.url = url; } public String getUrl() { return this.url; } public void setName(String name) { this.name = name; } public String getName() { return this.name; } }
自定義viewPager
ChildViewPager.java
主要重寫 onTouchEvent(),實現點選監聽和解決滑動衝突問題。因為在專案中當前介面為ScrollView,所以有滑動衝突問題。@Override public boolean onTouchEvent(MotionEvent arg0) { // TODO Auto-generated method stub //每次進行onTouch事件都記錄當前的按下的座標 curP.x = arg0.getX(); curP.y = arg0.getY(); if(arg0.getAction() == MotionEvent.ACTION_DOWN){ //記錄按下時候的座標 //切記不可用 downP = curP ,這樣在改變curP的時候,downP也會改變 downP.x = arg0.getX(); downP.y = arg0.getY(); //此句程式碼是為了通知他的父ViewPager現在進行的是本控制元件的操作,不要對我的操作進行干擾 getParent().requestDisallowInterceptTouchEvent(true); } if(arg0.getAction() == MotionEvent.ACTION_MOVE){ //此句程式碼是為了通知他的父ViewPager現在進行的是本控制元件的操作,不要對我的操作進行干擾 getParent().requestDisallowInterceptTouchEvent(true); } if(arg0.getAction() == MotionEvent.ACTION_UP){ //在up時判斷是否按下和鬆手的座標為一個點 這裡可以把判斷放鬆一點 //如果是一個點,將執行點選事件,這是我自己寫的點選事件,而不是onclick if(downP.x==curP.x && downP.y==curP.y){ onSingleTouch(); return true; } // return super.onTouchEvent(arg0); } return super.onTouchEvent(arg0); } /** * 單擊 */ public void onSingleTouch() { if (onSingleTouchListener!= null) { onSingleTouchListener.onSingleTouch(); } }
重頭戲來啦
BannerLayout.java
首先是初始化函式
public BannerLayout(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
LayoutInflater.from(context).inflate(R.layout.viewpager_banner, this);
setUpView();
}
private void setUpView() {
mViewPager = (ChildViewPager) findViewById(R.id.viewpager);
llPoints = (LinearLayout) findViewById(R.id.ll_points);
mViewPager.setOnSingleTouchListener(new ChildViewPager.OnSingleTouchListener() {
@Override
public void onSingleTouch() {
// TODO Auto-generated method stub
onClickImg.ItemId(currentId%ivList.size());
}
});
ivList = new ArrayList<>();
llPoints.removeAllViews();
}
這裡就能看到使用中的影子了,設定資料
/**
* @param dotId 圓點資源id
* @param ivList 引數的size必需相等,不然報錯
*/
public void startBanner(List<ImageView> ivList, int dotId) {
this.ivList = ivList;
for (int i = 0; i < ivList.size(); i++) {
view = new View(context);
view.setBackgroundDrawable(getResources()
.getDrawable(dotId));
initPoint(view, pointSmall);
view.setEnabled(false);
llPoints.addView(view);
}
initDataImg();
}
/**
* 設定資料
*/
private void initDataImg() {
ViewPagerAdapter adapter = new ViewPagerAdapter();
mViewPager.setAdapter(adapter);
mViewPager.setOnPageChangeListener(this);
llPoints.getChildAt(0).setEnabled(true);
initPoint(llPoints.getChildAt(0), pointBig);
mViewPager.setCurrentItem(idx);
imgHandler.sendEmptyMessageDelayed(MSG_UPDATE_IMAGE, MSG_DELAY);
}
這些都是viewPager的慣用方法。下邊說說自動輪播的實現。 自動輪播通過handle佇列機制呼叫實現,handle設定如下
/**
* 請求更新顯示的View。
*/
protected static final int MSG_UPDATE_IMAGE = 1;
/**
* 請求暫停輪播。
*/
protected static final int MSG_KEEP_SILENT = 2;
/**
* 請求恢復輪播。
*/
protected static final int MSG_BREAK_SILENT = 3;
/**
* 記錄最新的頁號,當用戶手動滑動時需要記錄新頁號,否則會使輪播的頁面出錯。 例如當前如果在第一頁,本來準備播放的是第二頁,而這時候使用者滑動到了末頁,
* 則應該播放的是第一頁,如果繼續按照原來的第二頁播放,則邏輯上有問題。
*/
protected static final int MSG_PAGE_CHANGED = 4;
// 輪播間隔時間
protected static long MSG_DELAY = 3000;
private Handler imgHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
// 檢查訊息佇列並移除未傳送的訊息,這主要是避免在複雜環境下訊息出現重複等問題。
if (imgHandler.hasMessages(MSG_UPDATE_IMAGE)) {
imgHandler.removeMessages(MSG_UPDATE_IMAGE);
}
switch (msg.what) {
case MSG_UPDATE_IMAGE:
mViewPager.setCurrentItem(currentId + 1);
// 準備下次播放
sendEmptyMessageDelayed(MSG_UPDATE_IMAGE, MSG_DELAY);
break;
case MSG_KEEP_SILENT:
// 只要不傳送訊息就暫停了
break;
case MSG_BREAK_SILENT:
sendEmptyMessageDelayed(MSG_UPDATE_IMAGE, MSG_DELAY);
break;
case MSG_PAGE_CHANGED:
// 記錄當前的頁號,避免播放的時候頁面顯示不正確。
// currentIcon = msg.arg1;
break;
default:
break;
}
}
};
在viewPager的監聽器onPageScrollStateChanged中我們可以使用handle中的方法達到想要的效果
@Override
public void onPageScrollStateChanged(int arg0) {
// Auto-generated method stub
switch (arg0) {
case ViewPager.SCROLL_STATE_DRAGGING:
imgHandler.sendEmptyMessage(MSG_KEEP_SILENT);
break;
case ViewPager.SCROLL_STATE_IDLE:
imgHandler.sendEmptyMessageDelayed(MSG_UPDATE_IMAGE, MSG_DELAY);
break;
default:
break;
}
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// Auto-generated method stub
}
@Override
public void onPageSelected(int position) {
// 切換選中的點
llPoints.getChildAt(previousSelectPosition).setEnabled(false); // 把前一個點置為normal狀態
initPoint(llPoints.getChildAt(previousSelectPosition), pointSmall);
llPoints.getChildAt(position % ivList.size()).setEnabled(true); // 把當前選中的position對應的點置為enabled狀態
initPoint(llPoints.getChildAt(position % ivList.size()), pointBig);
previousSelectPosition = position % ivList.size();
currentId = position;
imgHandler.sendMessage(Message.obtain(imgHandler, MSG_PAGE_CHANGED,
position, 0));
}
元件下載