本文将所有輪播圖的功能實作全放在了自定義ViewPager中,若你的ViewPager需要實作輪播功能,隻需要将ViewPager替換為CycleViewPager(注:本文V4包為低版本,如有需要,請自行将監聽更改為addOnPageChangeListener)。
首頁面代碼與正常使用ViewPager一緻,示範采用的是在代碼中執行個體CycleViewPager對象:
MainActivity代碼如下:
package zz.qby.cycleviewpager;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.FrameLayout;
import android.widget.ImageView;
/**
* 顯示首頁面
* @author qby
*/
public class MainActivity extends Activity {
private FrameLayout fl_cycleview;
private int[] resIds = new int[] { R.drawable.image1, R.drawable.image2,
R.drawable.image3, R.drawable.image4, R.drawable.image5 };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fl_cycleview = (FrameLayout) findViewById(R.id.fl_cycleview);
MyPageAdapter adapter = new MyPageAdapter();
viewPager.setAdapter(adapter);
// 可使用工具類将dp轉為px設定給LayoutParams
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
LayoutParams.MATCH_PARENT, );
fl_cycleview.addView(viewPager, params);
}
private class MyPageAdapter extends PagerAdapter {
@Override
public int getCount() {
return resIds.length;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView iv = new ImageView(getApplicationContext());
iv.setBackgroundResource(resIds[position]);
container.addView(iv);
return iv;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
}
布局代碼很簡單:
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<FrameLayout
android:id="@+id/fl_cycleview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
</FrameLayout>
</LinearLayout>
下面是本文重點,自定義ViewPager的代碼:
package zz.qby.cycleviewpager;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
/**
* @author qby
* @project CycleViewPager
* @create_time 00:08:36
* @des 自定義輪播圖,實作無限輪播、自動輪播、觸摸停止自動輪播
*/
public class CycleViewPager extends ViewPager {
//handler實作自動輪播
private static final int scrollTask = ;
private InnerAdapter innerAdapter;
private int position;
public CycleViewPager(Context context) {
super(context);
}
public CycleViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* 重寫頁面改變監聽
*/
@Override
public void setOnPageChangeListener(OnPageChangeListener listener) {
InnserOnPageChangeListener innserOnPageChangeListener = new InnserOnPageChangeListener(
listener);
super.setOnPageChangeListener(innserOnPageChangeListener);
}
/**
* 自定義監聽器實作頁面改變的監聽
* @author qby
*
*/
public class InnserOnPageChangeListener implements OnPageChangeListener {
private OnPageChangeListener listener;
public InnserOnPageChangeListener(OnPageChangeListener listener) {
this.listener = listener;
}
@Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
if (listener != null)
listener.onPageScrolled(position, positionOffset,
positionOffsetPixels);
}
@Override
public void onPageSelected(int position) {
CycleViewPager.this.position = position;
if (listener != null)
listener.onPageSelected(position);
}
@Override
public void onPageScrollStateChanged(int state) {
// 空閑 IDLE
if (state == ViewPager.SCROLL_STATE_IDLE) {
if (position == innerAdapter.getCount() - ) {
// A 最後一個條目
// 切換到position = 1的 條目
// 悄悄的切換
CycleViewPager.this.setCurrentItem(, false);
} else if (position == ) {
// D
CycleViewPager.this.setCurrentItem(
innerAdapter.getCount() - , false);
}
}
if (listener != null)
listener.onPageScrollStateChanged(state);
}
}
// 修正adapter
@Override
public void setAdapter(PagerAdapter adapter) {
// 修正adapter
// innerAdapter [DABCDA]
innerAdapter = new InnerAdapter(adapter);
//設定頁面改變的監聽,因為不需要用參數的listener做其他操作,傳入null即可
//高版本V4包,可使用addOnPageChangeLstener
setOnPageChangeListener(null);
super.setAdapter(innerAdapter);
// 切換到 A
this.setCurrentItem();
// 啟動輪播
startScroll();
}
//設定輪播間隔為2秒
@SuppressLint("HandlerLeak")
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case scrollTask:
handler.removeMessages(scrollTask);
CycleViewPager.this.setCurrentItem(position++);
handler.sendEmptyMessageDelayed(scrollTask, );
break;
default:
break;
}
}
};
/**
* 啟動輪播
*/
private void startScroll() {
handler.sendEmptyMessageDelayed(scrollTask, );
}
/**
* 修正傳入adapter的索引
* @author qby
*
*/
public class InnerAdapter extends PagerAdapter {
private PagerAdapter adapter;
public InnerAdapter(PagerAdapter adapter) {
this.adapter = adapter;
}
@Override
public int getCount() {
return adapter.getCount() + ;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return adapter.isViewFromObject(view, object);
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
adapter.destroyItem(container, position, object);
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
// position [0,1,2,3,4,5]
// 修正 position
if (position == ) {
// D --- >找到原來集合中的索引
position = adapter.getCount() - ;
} else if (position == getCount() - ) {
// A
position = ;
} else {
position -= ;
}
return adapter.instantiateItem(container, position);
}
}
/**處理按下時不自動輪播,松開後自動輪播*/
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
// 手指按下移除消息
handler.removeMessages(scrollTask);
break;
case MotionEvent.ACTION_MOVE:
break;
// 細節,觸摸可能在控件外才擡起,此時隻能監聽到取消事件
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
startScroll();
break;
}
return super.onTouchEvent(ev);
}
}