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

来源:互联网 发布:mac 音乐升降调编辑 编辑:程序博客网 时间:2024/05/18 01:36

        在安卓开发,我们经常看到一些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){returnnew 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;@Overridepublic void onPageScrollStateChanged(int arg0) {}@Overridepublic void onPageScrolled(int arg0, float arg1, int arg2) {}@Overridepublic 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{@Overridepublic void run() {currentItem=(currentItem + 1)% imageViewsList.size();handler.obtainMessage().sendToTarget();}}/** * 设置viewpager当前显示的页面 * */protected static class MyHandler extends Handler {  @Overridepublic 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;}@Overridepublic int getCount() {// TODO 自动生成的方法存根return imageViewsList.size();}@Overridepublic boolean isViewFromObject(View arg0, Object arg1) {// TODO 自动生成的方法存根return arg0==arg1;}@Overridepublic void destroyItem(ViewGroup container, int position, Object object) {container.removeView(imageViewsList.get(position));}@Overridepublic Object instantiateItem(ViewGroup container, final int position) {View view=imageViewsList.get(position);//为每页广告图片设置点击事件view.setOnClickListener(new OnClickListener() {@Overridepublic 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