在安卓开发,我们经常看到一些app的主页上面有一个banner广告界面,循环播放多个广告图片,也响应左右滑动事件,大家一定回想到ViewPager,确实该banner广告界面用到了ViewPager,无可厚非,当然大家也清楚,在实际开发中,广告图片一般加载的是网络图片,并且加载几张都有可能随时调整,所以为了banner更加切合实际开发中的应用,出于这些问题,自己亲自把项目中的实现的该功能自定义类分享给大家,共勉。
1,效果图(因为设备问题没有截取gif图片,效果我想大家一定能想到,隔几秒切换下一张照片,切换到最后一张,自动切换到第一张,循环播放)
下面我们进入主题,看如何实现的
2,首先我们来做这个小圆点,因为每个圆点都一样,所以为了简化代码,我们可以在values文件下的styles里面定义一个dot_style
<style name="dot_style">
<item name="android:layout_width">5dip</item>
<item name="android:layout_height">5dip</item>
<item name="android:background">@drawable/dot_normal</item>
<item name="android:layout_marginLeft">1.5dip</item>
<item name="android:layout_marginRight">1.5dip</item>
</style>
我们知道,当广告页切换到该页时,相应的小圆点指示导航图标与其他的显示不同,所以我们需要两个Shape资源,如下
dot_normal.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<solid android:color="@color/white" />
<corners android:radius="5dip" />
</shape>
dot_focused.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<solid android:color="@color/red" />
<corners android:radius="5dip" />
</shape>
3,有了以上的工作,下面进入初始化布局,直接上布局代码(因为在项目中牵扯到事件分发,所以自定义了viewpager,如果不需要,直接用自带的viewpager就可以,里面我们加入了六个导航圆点,也就是最多显示六个导航圆点,如果需要更多只需在布局中多添加几个,在不需要修改其他代码,自动根据要显示照片个数自动设置)
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="200dip" >
<FrameLayout
android:id="@+id/mainvideo_banner_FrameLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<com.suowei.appsuowei.myview.DefinedMainViewPager
android:id="@+id/vp_banner"
android:layout_width="match_parent"
android:layout_height="100dp" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:layout_marginBottom="10dp"
android:layout_marginTop="10dip"
android:gravity="center" >
<View
android:id="@+id/v_dot0"
style="@style/dot_style"
android:background="@drawable/dot_focused"
android:visibility="visible" />
<View
android:id="@+id/v_dot1"
style="@style/dot_style"
android:visibility="invisible" />
<View
android:id="@+id/v_dot2"
style="@style/dot_style"
android:visibility="invisible" />
<View
android:id="@+id/v_dot3"
style="@style/dot_style"
android:visibility="invisible" />
<View
android:id="@+id/v_dot4"
style="@style/dot_style"
android:visibility="invisible" />
<View
android:id="@+id/v_dot5"
style="@style/dot_style"
android:visibility="invisible" />
</LinearLayout>
</FrameLayout>
</merge>
3,自定义类源代码(在原码注释中讲解每段代码功能)
package com.suowei.appsuowei.myview;
import java.io.File;
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.example.appsuowei.R;
import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache;
import com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
import com.suowei.appsuowei.adapter.AdBannerAdapter;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
public class DefinedADView extends FrameLayout{
public static String IMAGE_CACHE_PATH = "SuoWeiAPP/imageloader/Cache";//照片缓存地址,改为自己的缓存地址
private ScheduledExecutorService scheduledExecutorService;
private static int currentItem;
private View dotView0,dotView1,dotView2,dotView3,dotView4;
private ArrayList<View> dotsList;//原始状态原点集合
private ArrayList<View> dotsNewList;//新状态原点集合
private ArrayList<ImageView> imageViewsList;
private static ViewPager vPager;
private MyHandler handler;
private ImageLoader imageLoader;
private DisplayImageOptions displayImageOptions;
public DefinedADView(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout.ad_main_banner, this);
handler=new MyHandler();
initData(context);
}
/**
* 初始化数据
* */
private void initData(Context context){
findADView();
initImageLoader(context);
}
/**
* 绑定控件
* */
protected void findADView(){
vPager=(ViewPager) findViewById(R.id.vp_banner);
vPager.addOnPageChangeListener(new HomeOnPageChangeListener());
dotView0=findViewById(R.id.v_dot0);
dotView1=findViewById(R.id.v_dot1);
dotView2=findViewById(R.id.v_dot2);
dotView3=findViewById(R.id.v_dot3);
dotView4=findViewById(R.id.v_dot4);
//将导航圆点装入dotsList集合中,大家注意dotview的visible为invisible,因为我们还不知道开发需要显示几个导航圆点
dotsList=new ArrayList<View>();
dotsList.add(dotView0);
dotsList.add(dotView1);
dotsList.add(dotView2);
dotsList.add(dotView3);
dotsList.add(dotView4);
}
/**
* 根据传入的size大小,设置相应多的原点状态为显示并add到集合中
* */
private void initDotView(int size){
dotsNewList=new ArrayList<View>();
for(int i=0;i<size;i++){
dotsList.get(i).setVisibility(View.VISIBLE);
dotsNewList.add(dotsList.get(i));
}
}
/**
* 初始化imageloader和displayImageOptions,第三方库异步加载网络图片的库,百度一搜一筐子,下载下来放到libs中,并配置构建路劲
* */
private void initImageLoader(Context context){
imageLoader=this.initedImageLoader(context);
displayImageOptions=this.initDisplayImageOptions(context);
}
/**
* 初始化ImageLoader方法
* */
public ImageLoader initedImageLoader(Context context) {
File cacheDir = com.nostra13.universalimageloader.utils.StorageUtils
.getOwnCacheDirectory(context,
IMAGE_CACHE_PATH);//照片缓存地址
DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
.cacheInMemory(true).cacheOnDisc(true).build();
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
context).defaultDisplayImageOptions(defaultOptions)
.memoryCache(new LruMemoryCache(12 * 1024 * 1024))
.memoryCacheSize(12 * 1024 * 1024)
.discCacheSize(32 * 1024 * 1024).discCacheFileCount(100)
.discCache(new UnlimitedDiscCache(cacheDir))
.threadPriority(Thread.NORM_PRIORITY - 2)
.tasksProcessingOrder(QueueProcessingType.LIFO).build();
ImageLoader.getInstance().init(config);
return ImageLoader.getInstance();
}
/**
* 初始化DisplayImageOptions方法
* */
public DisplayImageOptions initDisplayImageOptions(Context context){
return new DisplayImageOptions.Builder()
.showStubImage(R.drawable.bt_close)//正在缓冲中显示的照片
.showImageForEmptyUri(R.drawable.bt_close)//空地址显示的照片
.showImageOnFail(R.drawable.bt_close)//缓冲失败显示的照片
.cacheInMemory(true).cacheOnDisc(true)
.bitmapConfig(Bitmap.Config.RGB_565)
.imageScaleType(ImageScaleType.EXACTLY).build();
}
/**
* 设置照片路径,开发者调用该方法传入装网络图片地址的集合
* */
public void setUriImageView(List<String> ivUriList,Context context){
//新建相应 个数的ImageView,并用ImageLoader异步加载图片,并放入集合imageViewsList中
imageViewsList=new ArrayList<ImageView>();
for(int i=0;i<ivUriList.size();i++){
ImageView imageView=new ImageView(context);
imageView.setScaleType(ScaleType.FIT_XY);
imageLoader.displayImage(ivUriList.get(i), imageView, displayImageOptions);
imageViewsList.add(imageView);
}
initDotView(ivUriList.size());
//设置适配器
SetADAdatper(context);
}
/**
* 设置adapter
* */
private void SetADAdatper(Context context){
if(imageViewsList!=null){
vPager.setAdapter(new AdBannerAdapter(imageViewsList,context));
}
}
/**
* 调用scheduledExecutorService类启动viewpager自动切换,相关参数不懂可以百度搜索查阅
* @param isStart (true开始切换,false停止切换)
* */
public void startVPChange(Boolean isStart){
if(scheduledExecutorService==null){
scheduledExecutorService=Executors.newSingleThreadScheduledExecutor();
}
if(isStart){
scheduledExecutorService.scheduleAtFixedRate(new MyRunnable(), 4, 5, TimeUnit.SECONDS);
}
else {
scheduledExecutorService.shutdown();
}
}
/**
* viewpager监听事件,主要用来设置导航圆点的状态
* */
private class HomeOnPageChangeListener implements OnPageChangeListener{
private int oldPosition=0;
@Override
public void onPageScrollStateChanged(int arg0) {}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {}
@Override
public void onPageSelected(int arg0) {
currentItem=arg0;
//设置前一页导航圆点为正常状态
dotsNewList.get(oldPosition).setBackgroundResource(R.drawable.dot_normal);
//设置当前页导航圆点为聚焦状态
dotsNewList.get(arg0).setBackgroundResource(R.drawable.dot_focused);
oldPosition=arg0;
}
}
/**
* 自动切换线程,每次启动该线程,会重新计算viewpager当前显示的页面位置
* */
protected class MyRunnable implements Runnable{
@Override
public void run() {
currentItem=(currentItem + 1)% imageViewsList.size();
handler.obtainMessage().sendToTarget();
}
}
/**
* 设置viewpager当前显示的页面
* */
protected static class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
vPager.setCurrentItem(currentItem);
super.handleMessage(msg);
}
}
}
4,viewpager适配器代码
package com.suowei.appsuowei.adapter;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.Toast;
public class AdBannerAdapter extends PagerAdapter{
private ArrayList<ImageView> imageViewsList;
private Context context;
public AdBannerAdapter(ArrayList<ImageView> imageViewsList,Context context) {
super();
this.context=context;
this.imageViewsList = imageViewsList;
}
@Override
public int getCount() {
// TODO 自动生成的方法存根
return imageViewsList.size();
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
// TODO 自动生成的方法存根
return arg0==arg1;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(imageViewsList.get(position));
}
@Override
public Object instantiateItem(ViewGroup container, final int position) {
View view=imageViewsList.get(position);
//为每页广告图片设置点击事件
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context, "点击了第"+(position+1)+"张广告", Toast.LENGTH_SHORT).show();
}
});
container.addView(view);
return imageViewsList.get(position);
}
}
5,在activity的布局中,添加自定义好的DefinedADView,在activty主代码中只需调用以下两个方法即可实现了,
definedADView.setUriImageView(uriList, this);//第一个参数为网络图片地址的集合,简单吧,
definedADView.startVPChange(true);//这一步启动自动切换,就OK了
如果一旦启动了自动切换,会每隔一段时间会启动线程切换照片,所以为了节省内存,在activity的onpause或者onDestory那个生命周期中调用definedADView.startVPChange(false);关闭切换,你懂得。6,配置权限不可忘记哦
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
7、一定记住要下载Android 开源框架Universal-Image-Loader