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);            }        }    }}

最后来看看实现的效果
这里写图片描述

源码下载

3 0
原创粉丝点击