本文将所有轮播图的功能实现全放在了自定义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, 300);
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 = 88;
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() - 1) {
// A 最后一个条目
// 切换到position = 1的 条目
// 悄悄的切换
CycleViewPager.this.setCurrentItem(1, false);
} else if (position == 0) {
// D
CycleViewPager.this.setCurrentItem(
innerAdapter.getCount() - 2, 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(1);
// 启动轮播
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, 2000);
break;
default:
break;
}
}
};
/**
* 启动轮播
*/
private void startScroll() {
handler.sendEmptyMessageDelayed(scrollTask, 2000);
}
/**
* 修正传入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() + 2;
}
@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 == 0) {
// D --- >找到原来集合中的索引
position = adapter.getCount() - 1;
} else if (position == getCount() - 1) {
// A
position = 0;
} else {
position -= 1;
}
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);
}
}