Android 实现广告Banner循环轮播
来源:互联网 发布:js replaceall 转译 编辑:程序博客网 时间:2024/05/22 08:13
做了很多的App,发现广告Banner非常的常用,在这里就总结一下我的做法,先看看一个应用的广告Banner
1. ViewPager中展示和下载图片
下面我们来实现一个类似的广告Banner,主布局界面
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="5dp" tools:context=".MyBannerActivity"> <com.example.liuwangshu.mybanner.SlideShowView android:id="@+id/sv_photo" android:layout_width="match_parent" android:layout_height="160dp" android:background="@android:color/darker_gray" /></RelativeLayout>
在布局里引用了com.example.liuwangshu.mybanner.SlideShowView,这是自定义布局,继承FrameLayout,用来展示轮播图片和圆点。
SlideShowView构造函数为
public SlideShowView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); this.context = context; LayoutInflater.from(context).inflate(R.layout.layout_slideshow, this, true); imageViewsList = new ArrayList<ImageView>(); dotViewsList = new ArrayList<View>(); }
加载了布局文件,并且创建了两个List,分别存储图片和小圆点。
布局文件layout_slideshow.xml,里面定义了ViewPager用来显示图片,其他的用来显示圆点
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v4.view.ViewPager android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="match_parent" /> <LinearLayout android:id="@+id/dotLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="8dp" android:gravity="right" android:layout_alignParentBottom="true" android:orientation="horizontal"> <View android:id="@+id/v_dot1" android:layout_width="8dp" android:layout_height="8dp" android:background="@drawable/dot_focus" /> <View android:id="@+id/v_dot2" android:layout_width="8dp" android:layout_height="8dp" android:layout_marginLeft="5dp" android:background="@drawable/dot_blur" /> </LinearLayout></RelativeLayout>
这个自定义SlideShowView的核心方法为setView方法,用来接收将Activity传来imageUrls数组,初始化UI和实现轮播效果
public void setView(String[] imageUrls) { this.imageUrls = imageUrls; initUI(context); if (isAutoPlay) { startPlay(); } }
startPlay方法我后面会讲解到,先来看看initUI方法,这个方法通过一个for循环将轮播需要的图片地址填充到imageViewsList中,将需要的小圆点填充到dotViewsList,并创建了viewPager将imageViewsList传进去展示轮播图。
private void initUI(Context context) { if (imageUrls == null || imageUrls.length == 0) return; if (dotLayout != null) { dotLayout.removeAllViews(); } else { dotLayout = (LinearLayout) findViewById(R.id.dotLayout); } dotLayout.removeAllViews(); dotViewsList.clear(); imageViewsList.clear(); for (int i = 0; i < imageUrls.length; i++) { ImageView view = new ImageView(context); view.setTag(imageUrls[i]); view.setScaleType(ScaleType.FIT_XY); imageViewsList.add(view); ImageView dotView = new ImageView(context); 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); } viewPager = (ViewPager) findViewById(R.id.viewPager); viewPager.setFocusable(true); viewPager.setAdapter(new PhotoAdapter(imageUrls)); viewPager.setOnPageChangeListener(new MyPageChangeListener()); }
PhotoAdapter接收需要播放的图片地址在instantiateItem方法中用volley来下载图片
private class PhotoAdapter extends PagerAdapter { private String[] images; private LayoutInflater inflater; PhotoAdapter(String[] images) { this.images = images; } @Override public void destroyItem(View container, int position, Object object) { ((ViewPager) container).removeView(imageViewsList.get(position)); } @Override public Object instantiateItem(View container, final int position) { if (position > imageViewsList.size() - 1 || images.length < position + 1) { return null; } ImageView imageView = imageViewsList.get(position); if (!TextUtils.isEmpty(images[position])) { loadImageByVolley(imageView,images[position]); } ((ViewPager) container).addView(imageViewsList.get(position)); return imageViewsList.get(position); }...}
这里之所以采用volley下载图片,因为volley是默认开启硬盘缓存的,如果我们把应用杀掉并关掉网络,重新打开引用发现我们之前下载的图片仍显示在Banner界面上,不需要重新下载。loadImageByVolley方法很简单:
private void loadImageByVolley(ImageView imageView ,String imageUrl){ RequestQueue mQueue = Volley.newRequestQueue(context); final BitmapCache lruCache=new BitmapCache(); ImageLoader.ImageCache imageCache = new ImageLoader.ImageCache() { @Override public void putBitmap(String key, Bitmap value) { lruCache.putBitmap(key, value); } @Override public Bitmap getBitmap(String key) { return lruCache.getBitmap(key); } }; ImageLoader imageLoader = new ImageLoader(mQueue, imageCache); ImageLoader.ImageListener listener = ImageLoader.getImageListener( imageView, 0,0); imageLoader.get(imageUrl, listener); }
2. 实现播放
我们已经将数据传给PhotoAdapter并下载图片,剩下的就是播放了让我们看看 startPlay方法
private void startPlay() { scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); scheduledExecutorService.scheduleAtFixedRate(new SlideShowTask(), 1, 4, TimeUnit.SECONDS); }
startPlay方法创建了单线程化的线程池,并延时发送message来不断切换ViewPager的item:不清楚线程池的可以参考:android多线程(一)线程池
SlideShowTask中不断的发送message:
private class SlideShowTask implements Runnable { @Override public void run() { synchronized (viewPager) { currentItem = (currentItem + 1) % imageViewsList.size(); handler.obtainMessage().sendToTarget(); } } }
最后看看接收message的handler:
private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); viewPager.setCurrentItem(currentItem); } };
看到这都明白了吧就是通过消息来不断的通知UI线程的ViewPager不断的切换显示的条目,SlideShowView.java 的源码:
package com.example.liuwangshu.mybanner;import android.content.Context;import android.graphics.Bitmap;import android.graphics.drawable.Drawable;import android.os.Handler;import android.os.Message;import android.os.Parcelable;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.view.LayoutInflater;import android.view.View;import android.widget.FrameLayout;import android.widget.ImageView;import android.widget.ImageView.ScaleType;import android.widget.LinearLayout;import com.android.volley.RequestQueue;import com.android.volley.Response;import com.android.volley.VolleyError;import com.android.volley.toolbox.ImageLoader;import com.android.volley.toolbox.ImageRequest;import com.android.volley.toolbox.Volley;import java.util.ArrayList;import java.util.List;import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;public class SlideShowView extends FrameLayout { private final static int IMAGE_COUNT = 5; private final static int TIME_INTERVAL = 5; private final static boolean isAutoPlay = true; private String[] imageUrls; private String[] urls; private String[] titles; private String[] contents; private List<ImageView> imageViewsList; private List<View> dotViewsList; private ViewPager viewPager; private int currentItem = 0; private ScheduledExecutorService scheduledExecutorService; private Context context; // Handler private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); viewPager.setCurrentItem(currentItem); } }; private LinearLayout dotLayout; public SlideShowView(Context context) { this(context, null); } public SlideShowView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SlideShowView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); this.context = context; LayoutInflater.from(context).inflate(R.layout.layout_slideshow, this, true); imageViewsList = new ArrayList<ImageView>(); dotViewsList = new ArrayList<View>(); } public void setView(String[] imageUrls) { this.imageUrls = imageUrls; initUI(context); if (isAutoPlay) { startPlay(); } } public void setUrl(String[] urls) { this.urls = urls; } public void setTitles(String[] titles) { this.titles = titles; } public void setContents(String[] contents) { this.contents = contents; } private void startPlay() { scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); scheduledExecutorService.scheduleAtFixedRate(new SlideShowTask(), 1, 4, TimeUnit.SECONDS); } private void stopPlay() { scheduledExecutorService.shutdown(); } private void initUI(Context context) { if (imageUrls == null || imageUrls.length == 0) return; if (dotLayout != null) { dotLayout.removeAllViews(); } else { dotLayout = (LinearLayout) findViewById(R.id.dotLayout); } dotLayout.removeAllViews(); dotViewsList.clear(); imageViewsList.clear(); for (int i = 0; i < imageUrls.length; i++) { ImageView view = new ImageView(context); view.setTag(imageUrls[i]); view.setScaleType(ScaleType.FIT_XY); imageViewsList.add(view); ImageView dotView = new ImageView(context); 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); } viewPager = (ViewPager) findViewById(R.id.viewPager); viewPager.setFocusable(true); viewPager.setAdapter(new PhotoAdapter(imageUrls)); viewPager.setOnPageChangeListener(new MyPageChangeListener()); } private class PhotoAdapter extends PagerAdapter { private String[] images; private LayoutInflater inflater; PhotoAdapter(String[] images) { this.images = images; } @Override public void destroyItem(View container, int position, Object object) { ((ViewPager) container).removeView(imageViewsList.get(position)); } @Override public Object instantiateItem(View container, final int position) { if (position > imageViewsList.size() - 1 || images.length < position + 1) { return null; } ImageView imageView = imageViewsList.get(position); if (!TextUtils.isEmpty(images[position])) { loadImageByVolley(imageView,images[position]); } ((ViewPager) container).addView(imageViewsList.get(position)); return imageViewsList.get(position); } /** * 检查点击的轮播图是否可以跳转 * * @param position * @return */ private boolean isItemAvailable(int position) { boolean isUrlsAvaiable = null != urls && urls.length > position; boolean isTitiesAvaiable = null != titles && titles.length > position; boolean isContentsAvaiable = null != contents && contents.length > position; return isUrlsAvaiable && isTitiesAvaiable && isContentsAvaiable; } @Override public int getCount() { return imageViewsList.size(); } @Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == arg1; } @Override public void restoreState(Parcelable arg0, ClassLoader arg1) { } @Override public Parcelable saveState() { return null; } @Override public void startUpdate(View arg0) { } @Override public void finishUpdate(View arg0) { } } private class MyPageChangeListener implements OnPageChangeListener { boolean isAutoPlay = false; @Override public void onPageScrollStateChanged(int arg0) { switch (arg0) { case 1: isAutoPlay = false; break; case 2: isAutoPlay = true; break; case 0: if (viewPager.getCurrentItem() == viewPager.getAdapter() .getCount() - 1 && !isAutoPlay) { viewPager.setCurrentItem(0); } else if (viewPager.getCurrentItem() == 0 && !isAutoPlay) { viewPager .setCurrentItem(viewPager.getAdapter().getCount() - 1); } break; } } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public void onPageSelected(int pos) { currentItem = pos; for (int i = 0; i < dotViewsList.size(); i++) { if (i == pos) { dotViewsList.get(pos) .setBackgroundResource(R.drawable.dot_focus); } else { dotViewsList.get(i) .setBackgroundResource(R.drawable.dot_blur); } } } } private class SlideShowTask implements Runnable { @Override public void run() { synchronized (viewPager) { currentItem = (currentItem + 1) % imageViewsList.size(); handler.obtainMessage().sendToTarget(); } } } private void loadImageByVolley(ImageView imageView ,String imageUrl){ RequestQueue mQueue = Volley.newRequestQueue(context); final BitmapCache lruCache=new BitmapCache(); ImageLoader.ImageCache imageCache = new ImageLoader.ImageCache() { @Override public void putBitmap(String key, Bitmap value) { lruCache.putBitmap(key, value); } @Override public Bitmap getBitmap(String key) { return lruCache.getBitmap(key); } }; ImageLoader imageLoader = new ImageLoader(mQueue, imageCache); ImageLoader.ImageListener listener = ImageLoader.getImageListener( imageView, 0,0); imageLoader.get(imageUrl, listener); } private void destoryBitmaps() { for (int i = 0; i < imageViewsList.size(); i++) { ImageView imageView = imageViewsList.get(i); Drawable drawable = imageView.getDrawable(); if (drawable != null) { drawable.setCallback(null); } } }}
最后来看看实现的效果
源码下载
- Android 实现广告Banner循环轮播
- Android 实现广告Banner循环轮播
- Android实现Banner界面广告图片循环轮播
- Android实现Banner界面广告图片循环轮播
- android实现banner界面广告图片循环轮播(包括手动活动轮播)
- Android实现Banner界面广告图片循环轮播(包括实现手动滑动循环)
- Android实现Banner界面广告图片循环轮播(包括实现手动滑动循环)
- Android实现Banner界面广告图片循环轮播(包括实现手动滑动循环)
- Android实现Banner界面广告图片循环轮播(包括实现手动滑动循环)
- Android实现Banner界面广告图片循环轮播(包括实现手动滑动循环)
- Android实现Banner界面广告图片循环轮播(包括实现手动滑动循环)
- Android实现Banner图片循环轮播
- Android实现Banner界面循环轮播
- android Banner 广告轮播
- Android实现一款不错Banner界面广告图片循环轮播
- Android UI - 实现广告Banner轮播效果
- Android UI - 实现广告Banner轮播效果
- Android UI 实现广告 Banner 轮播效果
- POJ1836 双向LIS
- Handler, Loop, MessageQueue的工作原理
- MySQL优化之BTree索引使用规则
- IOS编程中程序员真爱的不良习惯
- Ubuntu 装python3,但是不要改动系统默认python解释器的版本,源码安装的步骤
- Android 实现广告Banner循环轮播
- 1.开始在leetCode中刷题的一些感受
- IOS消息推送。
- Android推送机制
- 题目1032:ZOJ
- [转]annotation配置springMVC的方法了事务不起作用
- Zookeeper 笔记问答
- 棋牌游戏开发之地主AI算法实现
- Dreamweaver CS6最新官方正式中文破解版(32位、64位)