Demo实现的效果图如下:
工程目录如下图:
一个Application,一个实体类,一个Activity,另一个是自定义的AutoPlayingViewPager继承FrameLayout。
首先看一下自定义的AutoPlayingViewPager,功能都在这里实现。采用了第三方图片加载框架:universal_image_loader;
package com.skycracks.autoplayingviewpager;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import com.nostra13.universalimageloader.core.ImageLoader;
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.support.v4.view.ViewPager.OnPageChangeListener;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Scroller;
import android.widget.TextView;
/**
* 创建时间: 2016年1月10日 下午3:43:22
* 版本: [v1.0]
* 类描述: 实现ViewPager轮播图
* 使用了ImageLoader 对图片进行加载,所以使用前必须初始化ImageLoader
* stopPlaying() 当轮播所在页面不在顶栈时,有必要停止定时并且释放资源
* startPlaying() 当再次恢复时调用
*
*/
public class AutoPlayingViewPager extends FrameLayout {
private final static String TAG = "AutoPlayingViewPager";
/**
* 轮播图图片数量
*/
private int IMAGE_COUNT;
/**
* 自动轮播的时间间隔
*/
private final static int TIME_INTERVAL = 5;
/**
* 切换图片过度时间
*/
private int swapDuration = 1000;
/**
* 默认图片资源(本地图片资源Id)
*/
private int [] defaultIds = new int[] {
R.drawable.image01,R.drawable.image02,
R.drawable.image03,R.drawable.image04,R.drawable.image05};
/**
* 默认图片资源(图片URL地址)
*/
private String [] defaultUrl = new String[] {
"http://g.hiphotos.baidu.com/imgad/pic/item/a8773912b31bb051be533b24317adab44aede043.jpg",
"http://g.hiphotos.baidu.com/imgad/pic/item/c75c10385343fbf22c362d2fb77eca8065388fa0.jpg",
"http://liaoning.sinaimg.cn/2014/1111/U10435P1195DT20141111220802.jpg",
"http://photocdn.sohu.com/20151124/mp43786429_1448294862260_4.jpeg",
"http://h.hiphotos.baidu.com/image/pic/item/faedab64034f78f0b00507c97e310a55b3191cf9.jpg" };
private String [] defaultTitle = new String [] {
"今晚打老虎","今晚打松鼠","今晚打LOL","今晚打DOTA1","今晚打DOTA2"};
/**
* 自定义轮播图资源
*/
private List mAutoPlayInfoList;
/**
* 放圆点的View的list
*/
private List dotViewsList;
/**
* 轮播容器
*/
private ViewPager mViewPager;
/**
* 当前轮播页
*/
private int currentItem = 0;
/**
* 定时器对象
*/
private ScheduledExecutorService scheduledExecutorService;
private Context mContext;
private LayoutInflater mInflate;
/**
* ViewPageItem点击回调接口
*/
private OnPageItemClickListener onPageItemClickListener;
public void setOnPageItemClickListener(OnPageItemClickListener onPageItemClickListener){
this.onPageItemClickListener = onPageItemClickListener;
}
public interface OnPageItemClickListener{
/**
* ViewPageItem点击事件回调
*/
void onPageItemClick(int position, String adLink);
}
/**
* 消息处理器、设置当前显示页
*/
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
mViewPager.setCurrentItem(currentItem);
}
};
public AutoPlayingViewPager(Context context) {
this(context, null);
}
public AutoPlayingViewPager(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public AutoPlayingViewPager(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
this.mContext = context;
initData();
}
/**
* 通过本地图片资源Id获得默认的数据
*/
private List getImageIdAutoPlayInfoList(int [] imageIds){
List autoPlayInfoList = new ArrayList();
for(int i = 0 ; i < imageIds.length ; i ++){
AutoPlayInfo autoPlayInfo = new AutoPlayInfo();
autoPlayInfo.setImageId(imageIds[i]);
autoPlayInfoList.add(autoPlayInfo);
}
return autoPlayInfoList;
}
/**
* 通过图片URL地址获得默认的数据
*/
private List getDefaultUrlAutoPlayInfoList(){
List autoPlayInfoList = new ArrayList();
for(int i = 0 ; i < defaultUrl.length ; i ++){
AutoPlayInfo autoPlayInfo = new AutoPlayInfo();
autoPlayInfo.setImageUrl(defaultUrl[i]);
autoPlayInfo.setAdLinks("http://m.baidu.com");
autoPlayInfo.setTitle(defaultTitle[i]);
autoPlayInfoList.add(autoPlayInfo);
}
return autoPlayInfoList;
}
/**
* 初始化
* @param imageIds 需要加载的图片Id,根据传入数量动态创建容器。
* @return
*/
public AutoPlayingViewPager initialize(int [] imageIds) {
if (imageIds != null && imageIds.length != 0) {
mAutoPlayInfoList = getImageIdAutoPlayInfoList(imageIds);
} else {//没有数据使用默认的图片资源
mAutoPlayInfoList = getImageIdAutoPlayInfoList(defaultIds);
}
IMAGE_COUNT = mAutoPlayInfoList.size();
return this;
}
/**
* 初始化
*
* @param imageUrls 需要加载的图片地址,根据传入数量动态创建容器。
* @return
*/
public AutoPlayingViewPager initialize(List autoPlayInfoList) {
if (autoPlayInfoList != null && !autoPlayInfoList.isEmpty()) {
mAutoPlayInfoList = autoPlayInfoList;
} else {//没有数据使用默认的图片资源
mAutoPlayInfoList = getDefaultUrlAutoPlayInfoList();
}
IMAGE_COUNT = mAutoPlayInfoList.size();
return this;
}
/**
* 设置图片之间自动切换时间
*
* @param duration
* 切换时间
* @return
*/
public AutoPlayingViewPager setSwapDuration(int duration) {
this.swapDuration = duration;
return this;
}
/**
* 开始轮播图切换 轮播之前必须调initialize()及build()
*/
public void startPlaying() {
scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
scheduledExecutorService.scheduleAtFixedRate(new SlideShowTask(), 1,
TIME_INTERVAL, TimeUnit.SECONDS);
}
/**
* 停止轮播释放资源
*/
public void stopPlaying() {
scheduledExecutorService.shutdown();
}
/**
* 初始化相关Data
*/
private void initData() {
dotViewsList = new ArrayList();
}
/**
* 初始化Views 及组件UI
*/
public void build() {
if (mAutoPlayInfoList == null || mAutoPlayInfoList.isEmpty()) {
Log.d(TAG, "init image fail ");
return;
}
mInflate = LayoutInflater.from(mContext);
mInflate.inflate(R.layout.view_layout_slideshow,this, true);
LinearLayout dotLayout = (LinearLayout) findViewById(R.id.dotLayout);
dotLayout.removeAllViews();// 清除布局中的子视图,下面使用代码动态添加与图片对应的圆点
// 热点个数与图片数量相等
for (int i = 0; i < IMAGE_COUNT; i++) {
ImageView dotView = new ImageView(mContext);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.leftMargin = 4;
params.rightMargin = 4;
dotLayout.addView(dotView, params);
dotViewsList.add(dotView);
}
mViewPager = (ViewPager) findViewById(R.id.viewPager);
setViewPagerScrollSpeed();
mViewPager.setFocusable(true);
mViewPager.setOffscreenPageLimit(2);// 设置缓存页面,当前页面的相邻N各页面都会被缓存
mViewPager.setAdapter(new AutoPlayingPagerAdapter());
AutoPlayingPageChangeListener mPageChangeListener = new AutoPlayingPageChangeListener();
mViewPager.addOnPageChangeListener(mPageChangeListener);
}
/**
* 填充ViewPager的页面适配器
*/
private class AutoPlayingPagerAdapter extends PagerAdapter {
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
@Override
public Object instantiateItem(ViewGroup container, final int position) {
final AutoPlayInfo autoPlayInfo = mAutoPlayInfoList.get(position % IMAGE_COUNT);
View view = mInflate.inflate(R.layout.item_label_auto_play_viewpager, null);
ImageView imageView = (ImageView) view.findViewById(R.id.img_item_auto_play);
TextView labelTitle = (TextView) view.findViewById(R.id.tv_item_label_title);
/* if(!TextUtils.isEmpty(autoPlayInfo.getAdLinks())){//有链接时才添加监听
}*/
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
onPageItemClickListener.onPageItemClick(position % IMAGE_COUNT,autoPlayInfo.getAdLinks());
}
});
if(!TextUtils.isEmpty(autoPlayInfo.getImageUrl())){//通过URL时使用ImageLoader加载图片
ImageLoader.getInstance().displayImage(autoPlayInfo.getImageUrl(),imageView);
}else if(autoPlayInfo.getImageId() != 0){//本地图片时直接设置
imageView.setImageResource(autoPlayInfo.getImageId());
}
if(!TextUtils.isEmpty(autoPlayInfo.getTitle())){//有标题数据才显示
labelTitle.setText(autoPlayInfo.getTitle());
}else{//没有标题数据不显示文本透明背景
labelTitle.setBackgroundDrawable(null);
}
container.addView(view);
return view;
}
@Override
public int getCount() {
return Integer.MAX_VALUE;
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}
}
/**
* ViewPager的监听器 当ViewPager中页面的状态发生改变时调用
*
*/
private class AutoPlayingPageChangeListener implements OnPageChangeListener {
// boolean isChange = false;
@Override
public void onPageScrollStateChanged(int arg0) {
switch (arg0) {
case 1:// 手势滑动,空闲中
// isChange = false;
break;
case 2:// 界面切换中
// isChange = true;
break;
case 0:// 滑动结束,即切换完毕或者加载完毕
break;
}
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageSelected(int pos) {
currentItem = pos;
int p = pos % IMAGE_COUNT;
for (int i = 0; i < dotViewsList.size(); i++) {
if (i == p) {
dotViewsList.get(p).setBackgroundResource(
R.drawable.icon_cricle_check);
} else {
dotViewsList.get(i).setBackgroundResource(
R.drawable.icon_cricle_uncheck);
}
}
}
}
/**
* 执行轮播图切换任务
*
*/
boolean isLR = false;
private class SlideShowTask implements Runnable {
@Override
public void run() {
synchronized (mViewPager) {
currentItem++;
handler.obtainMessage().sendToTarget();
}
}
}
/**
* 使用反射往ViewPager中设置新的Scroller对象 覆盖默认的setCurrentItem切换时间
*/
private void setViewPagerScrollSpeed() {
try {
Field mScroller = null;
mScroller = ViewPager.class.getDeclaredField("mScroller");
mScroller.setAccessible(true);
FixedSpeedScroller scroller = new FixedSpeedScroller(
mViewPager.getContext());
mScroller.set(mViewPager, scroller);
} catch (NoSuchFieldException e) {
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
}
}
class FixedSpeedScroller extends Scroller {
public FixedSpeedScroller(Context context) {
super(context);
}
public FixedSpeedScroller(Context context, Interpolator interpolator) {
super(context, interpolator);
}
public FixedSpeedScroller(Context context, Interpolator interpolator,
boolean flywheel) {
super(context, interpolator, flywheel);
}
@Override
public void startScroll(int startX, int startY, int dx, int dy,
int duration) {
super.startScroll(startX, startY, dx, dy, swapDuration);
}
@Override
public void startScroll(int startX, int startY, int dx, int dy) {
super.startScroll(startX, startY, dx, dy, swapDuration);
}
}
}
当然想用上ImageLoad而必须在Application里面注册一下:
@Override
public void onCreate() {
super.onCreate();
initImageLoader();
}
/**
* 初始化UIL,这里初始化以后,就不在初始化了
*/
public void initImageLoader() {
DisplayImageOptions.Builder options = new DisplayImageOptions.Builder()
.cacheInMemory(true)// 内存缓存
.cacheOnDisk(true)// 磁盘缓存
.showImageOnFail(R.drawable.ic_faile)//加载失败显示的图片
.considerExifParams(true)// 是否考虑EXIF信息,比如拍照方向
.displayer(new FadeInBitmapDisplayer(300));//淡入动画
ImageLoaderConfiguration.Builder config = new ImageLoaderConfiguration.Builder(getApplicationContext());
// 取消缓存多张尺寸不同的同一张图片
config.denyCacheImageMultipleSizesInMemory();
// 设置显示选项
config.defaultDisplayImageOptions(options.build());
// 生成缓存文件的生成器,保证唯一的文件名,可以不设置,默认使用hash算法,也是可以保证不重名的
config.diskCacheFileNameGenerator(new Md5FileNameGenerator());
// 磁盘缓存大小
config.diskCacheSize(100 * 1024 * 1024); // 100 MB
// 内存缓存大小
config.memoryCacheSize((int) (Runtime.getRuntime().freeMemory() / 4));
// 任务处理顺序,默认是FIFO 先进先出, LIFO 后进先出
config.tasksProcessingOrder(QueueProcessingType.LIFO);
// 打印调试日志
config.writeDebugLogs(); // Remove for release app
ImageLoader.getInstance().init(config.build());
}
最关键的就是调用:
布局直接调用自定义的ViewPager:
"http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<com.skycracks.autoplayingviewpager.AutoPlayingViewPager
android:id="@+id/auto_play_viewpager"
android:layout_width="match_parent"
android:layout_height="200dp" >
com.skycracks.autoplayingviewpager.AutoPlayingViewPager>
主方法中运用很简单,只需把接收的对象集合传到自定义的AutoPlayingViewPager。
看代码:
package com.skycracks.autoplayingviewpager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.Toast;
import com.skycracks.autoplayingviewpager.AutoPlayingViewPager.OnPageItemClickListener;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private AutoPlayingViewPager mAutoPlayingViewPager;
/**
* 模拟网络请求获取的图片URL
*/
private String [] imageUrl = new String[] {
"http://g.hiphotos.baidu.com/image/pic/item/d0c8a786c9177f3e117088eb75cf3bc79e3d568b.jpg",
"http://upload.cebnet.com.cn/2014/1217/1418776413348.jpg",
"http://n.sinaimg.cn/transform/20150917/7DDk-fxhytwp5363222.jpg",
"http://n.sinaimg.cn/transform/20151019/YtA_-fxivsce6931363.jpg"
};
private String [] imageTitle = new String [] {
"赵丽颖","高圆圆","王鸥","唐嫣"};
private List mAutoPlayInfoList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAutoPlayingViewPager = (AutoPlayingViewPager) findViewById(R.id.auto_play_viewpager);
mAutoPlayInfoList=new ArrayList<>();
for(int i = 0 ; i < imageUrl.length ; i ++){
//把模拟的数据添加到集合里面
AutoPlayInfo autoPlayInfo = new AutoPlayInfo();
autoPlayInfo.setImageUrl(imageUrl[i]);
autoPlayInfo.setAdLinks("");
autoPlayInfo.setTitle(imageTitle[i]);
mAutoPlayInfoList.add(autoPlayInfo);
}
//通过这个方法把集合传进去,并设置图片的点击事件,可以做跳转
mAutoPlayingViewPager.initialize(mAutoPlayInfoList).build();
mAutoPlayingViewPager.setOnPageItemClickListener(onPageItemClickListener);
}
private OnPageItemClickListener onPageItemClickListener = new OnPageItemClickListener() {
@Override
public void onPageItemClick(int position, String adLink) {
Toast.makeText(MainActivity.this,"第"+position,Toast.LENGTH_LONG).show();
}
};
@Override
public void onStart() { //当Activity onRestart();还要执行,
//没有数据时不执行startPlaying,避免执行几次导致轮播混乱
if(mAutoPlayInfoList != null && !mAutoPlayInfoList.isEmpty()){
mAutoPlayingViewPager.startPlaying();
}
super.onResume();
}
@Override
public void onPause() {
mAutoPlayingViewPager.stopPlaying();
super.onPause();
}
}
最后几个就是实体类:
public class AutoPlayInfo {
//轮播图片URL
private String imageUrl;
//轮播本地图片资源Id
private int imageId;
//链接
private String adLinks;
//图片对应的标题
private String title;
public String getImageUrl() {
return imageUrl;
}
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
public int getImageId() {
return imageId;
}
public void setImageId(int imageId) {
this.imageId = imageId;
}
public String getAdLinks() {
return adLinks;
}
public void setAdLinks(String adLinks) {
this.adLinks = adLinks;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
另外,还有一种通过自定义ViewPager实现和本博文相同效果的广告界面Demo,这里就不再贴代码,可以通过如下地址下载:
http://blog.csdn.net/stevenhu_223/article/details/45577781
http://download.csdn.net/detail/stevenhu_223/8697903