安卓开发中实现广告图片自动切换的ViewPager广告栏的自定义类(可以根据广告数自动设置导航圆形图标个数)

        在安卓开发,我们经常看到一些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








  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值