首页 > 代码库 > 广告banner:手动滑动切换,自动切换,点击跳转,异步加载网络图片

广告banner:手动滑动切换,自动切换,点击跳转,异步加载网络图片

效果图:

 

技术分享

该banner功能有自动切换图片,点击图片可以自定义事件,手动滑动切换,异步加载图片

代码说话:

布局文件:

 

<!-- 广告位 -->            <FrameLayout                android:id="@+id/new_recommend"                android:layout_width="fill_parent"                android:layout_height="wrap_content" >                <com.cyou.cmall.ui.HorizontalViewPager                    android:id="@+id/viewpager"                    android:layout_width="fill_parent"                    android:layout_height="fill_parent" />                <LinearLayout                    android:id="@+id/ll_indicator"                    android:layout_width="wrap_content"                    android:layout_height="wrap_content"                    android:layout_gravity="bottom"                    android:orientation="horizontal"                    android:paddingBottom="8dp"                    android:paddingLeft="26dip" />            </FrameLayout>


布局文件中我自定义了一个HorizontalViewPager,它是在viewpager的基础上做了一些修改,之所以这样做是因为,项目中使用到了下拉刷新控件,该布局最外层还有一个scrollview,会导致scrollview将手势事件拦截,而viewpager得不到滑动手势

 

下面是HorizontalViewPager的代码,如果不需要处理滑动手势,完全可以使用系统的viewpager控件

 

/** * 复写该控件是因为在PullToRefreshScrollView中,viewpager无法水平滑动 * * @author wangwei_cs */public class HorizontalViewPager extends ViewPager {    private GestureDetector mGestureDetector;    public HorizontalViewPager(Context context, AttributeSet attrs) {        super(context, attrs);        init(context);    }    public HorizontalViewPager(Context context) {        super(context);        init(context);    }    private void init(Context context) {        mGestureDetector = new GestureDetector(context, new YScrollDetector());    }    @Override    public boolean dispatchTouchEvent(MotionEvent ev) {        boolean dispatchTouchEvent = super.dispatchTouchEvent(ev);        if (dispatchTouchEvent) {            if (mGestureDetector.onTouchEvent(ev)) {                //请求父类放弃事件的处理                requestDisallowInterceptTouchEvent(true);            }        }        return dispatchTouchEvent;    }    class YScrollDetector extends SimpleOnGestureListener {        @Override        public boolean onScroll(MotionEvent e1, MotionEvent e2,                float distanceX, float distanceY) {            // 如果我们滚动更接近水平方向,返回true,自己处理,否则,让出处理权限            return (Math.abs(distanceX) > Math.abs(distanceY));        }    }}</span>


言归正传:在程序oncreate方法中调用一下方法

 

    /**     * 初始化推荐广告专区     */    private void initRecommendAd() {        HorizontalViewPager mViewPager = (HorizontalViewPager) findViewById(R.id.viewpager);        mIndicatorLayout = (LinearLayout) findViewById(R.id.ll_indicator);        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(                android.widget.FrameLayout.LayoutParams.MATCH_PARENT, height * 24 / 100);        mViewPager.setLayoutParams(params);        AdImagePagerAdapter mPagerAdapter = new AdImagePagerAdapter(mCxt, imageUrls, new ViewPagerItemClickListener() {            @Override            public void OnViewPagerItemClick(int position) {                if (imageUrls.size() > 0) {                    if (imageUrls.size() == 1) {                        boolean enable = urlEnable(imageUrls.get(0));                        if (enable) {                            handleClickEvent(position);                        }                    } else {                        handleClickEvent(position);                    }                }            }        });        List<String> lastAdUrls = getLastAdUrls();        if (lastAdUrls == null || lastAdUrls.size() == 0) {            // 没有记录上一次广告url信息,添加一个无效url路径            imageUrls.add(Constants.INVALID_URL);            LogHelper.e(TAG, "no last ad record");        } else {            LogHelper.e(TAG, "show last ad record");            imageUrls.addAll(lastAdUrls);        }        mAdComponent = new RecommendAdComponent(mCxt, mViewPager, mPagerAdapter, imageUrls, 5000,                mIndicatorLayout);        mAdComponent.startUpAdComponent();        mPagerAdapter.notifyDataSetChanged();    }

 

 


下面是AdImagePagerAdapter的源码

 

import java.util.List;import android.content.Context;import android.graphics.Bitmap;import android.support.v4.view.PagerAdapter;import android.view.LayoutInflater;import android.view.View;import android.view.View.OnClickListener;import android.view.ViewGroup;import android.widget.AdapterView;import android.widget.AdapterView.OnItemClickListener;import android.widget.ImageView;import android.widget.ProgressBar;import android.widget.Toast;import com.nostra13.universalimageloader.core.DisplayImageOptions;import com.nostra13.universalimageloader.core.ImageLoader;import com.nostra13.universalimageloader.core.assist.FailReason;import com.nostra13.universalimageloader.core.assist.ImageScaleType;import com.nostra13.universalimageloader.core.assist.SimpleImageLoadingListener;import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;/** * 无限循环adapter *  * @author wangwei_cs */public class AdImagePagerAdapter extends PagerAdapter {    protected static final String TAG = "AdImagePagerAdapter";    private List<String> imageUrls;    private LayoutInflater inflater;    private Context mCxt;    private ViewPagerItemClickListener mListener;    protected ImageLoader imageLoader;    private DisplayImageOptions options;    public AdImagePagerAdapter(Context context, List<String> imageUrls, ViewPagerItemClickListener listener) {        this.imageUrls = imageUrls;        this.mCxt = context;        inflater = LayoutInflater.from(context);        this.mListener = listener;        imageLoader = ImageLoader.getInstance();        options = new DisplayImageOptions.Builder()                .showImageForEmptyUri(R.drawable.ad_default)                .showImageOnFail(R.drawable.ad_default)                .showImageOnLoading(R.drawable.ad_default)                .resetViewBeforeLoading(true)                .cacheOnDisc(true)                .imageScaleType(ImageScaleType.EXACTLY)                .bitmapConfig(Bitmap.Config.RGB_565)                .considerExifParams(true)                .displayer(new FadeInBitmapDisplayer(300))                .build();    }    @Override    public int getCount() {        if (imageUrls.size() < 2) {            return imageUrls.size();        }        return Integer.MAX_VALUE;    }    @Override    public boolean isViewFromObject(View arg0, Object arg1) {        return arg0 == arg1;    }    @Override    public Object instantiateItem(ViewGroup container, int position) {        final int index = position % imageUrls.size();        View view = inflater.inflate(R.layout.item_pager_image, container, false);        assert view != null;        ImageView imageView = (ImageView) view.findViewById(R.id.image);        final ProgressBar spinner = (ProgressBar) view.findViewById(R.id.img_loading);        imageLoader.displayImage(imageUrls.get(index), imageView, options,                new SimpleImageLoadingListener() {                    @Override                    public void onl oadingStarted(String imageUri, View view) {                        spinner.setVisibility(View.VISIBLE);                    }                    @Override                    public void onl oadingFailed(String imageUri, View view, FailReason failReason) {                        String message = null;                        switch (failReason.getType()) {                            case IO_ERROR:                                message = "Input/Output error";                                break;                            case DECODING_ERROR:                                message = "Image can‘t be decoded";                                break;                            case NETWORK_DENIED:                                message = "Downloads are denied";                                break;                            case OUT_OF_MEMORY:                                message = "Out Of Memory error";                                break;                            case UNKNOWN:                                message = "Unknown error";                                break;                        }                        LogHelper.e(TAG, message);                        spinner.setVisibility(View.GONE);                    }                    @Override                    public void onl oadingComplete(String imageUri, View view, Bitmap loadedImage) {                        spinner.setVisibility(View.GONE);                    }                });        view.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                if (mListener !=null) {                    mListener.OnViewPagerItemClick(index);                }            }        });        container.addView(view);        return view;    }    @Override    public void destroyItem(ViewGroup container, int position, Object object) {        container.removeView((View) object);    }}

 

 

 

 

下面是重点的RecommendAdComponent自定义的广告推荐组件

 

import android.annotation.SuppressLint;import android.content.Context;import android.os.Handler;import android.support.v4.view.PagerAdapter;import android.support.v4.view.ViewPager;import android.support.v4.view.ViewPager.OnPageChangeListener;import android.support.v4.view.ViewPager.PageTransformer;import android.view.View;import android.view.ViewGroup.LayoutParams;import android.view.animation.AnimationUtils;import android.widget.ImageView;import android.widget.LinearLayout;import java.util.List;import java.util.Timer;import java.util.TimerTask;/** * 展示广告轮转的组件 *  * @author wangwei_cs */public class RecommendAdComponent {    /**     * 无效的图片切换时间,如果为0 表示不自动切换     */    public static final int SWITCH_TIME_INVALID = 0;    private Context mCxt;    // 图片url集合    private List<String> mImgUrls;    // 图片切换时间    private int mSwitchTime;    //自动滚动的定时器     private Timer mTimer;    // 显示圆点指示器的布局    private LinearLayout mIndicatorLayout;    private ViewPager mViewPager;    private PagerAdapter mPagerAdapter;    private int currentIndex; // 当前页面,在0和getSize()直接    private int pagerCurrent;//在viewpager中,的当前页面,取值在0和Integer.MAX_VALUE之间    private boolean timeRunning;    /**     * @param context     * @param viewpager viewPager组件     * @param pagerAdapter     * @param adUrls 装有图片url的集合     * @param switchTime 图片切换时间(ms) {@link RecommendAdComponent#SWITCH_TIME_INVALID}:不自动切换     * @param indicatorLayout 显示圆点指示器的布局     */    public RecommendAdComponent(Context context, ViewPager viewpager, PagerAdapter pagerAdapter, List<String> adUrls, int switchTime,            LinearLayout indicatorLayout) {        this.mCxt = context;        this.mViewPager = viewpager;        this.mPagerAdapter = pagerAdapter;        this.mImgUrls = adUrls;        this.mSwitchTime = switchTime;        this.mIndicatorLayout = indicatorLayout;        initIndicatorLayout();        mViewPager.setOnPageChangeListener(new MyOnPageChangeListener());//        setViewpagerAnimator();    }    /**     * 初始化指示器     */    private void initIndicatorLayout() {        ImageView iv = null;        if (mIndicatorLayout != null && getSize() < 2) {            // 如果只有一第图时不显示圆点容器            mIndicatorLayout.setVisibility(View.INVISIBLE);        } else if (mIndicatorLayout != null) {            mIndicatorLayout.setVisibility(View.VISIBLE);            for (int i = 0; i < getSize(); i++) {                iv = new ImageView(mCxt);                iv.setTag(i);                int padding = mCxt.getResources().getDimensionPixelSize(R.dimen.indicator_padding);                LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,                        LayoutParams.WRAP_CONTENT);                params.setMargins(padding, 0, padding, 0);                mIndicatorLayout.addView(iv, params);            }        }    }    private void resetIndicatorLayout() {        mIndicatorLayout.removeAllViews();        initIndicatorLayout();    }    /**     * 给viewPager设置动画     */    private void setViewpagerAnimator(){        if (mViewPager !=null) {            PageTransformer pageTransformer=new PageTransformer() {                                @Override                public void transformPage(View view, float arg1) {//                    view.setAnimation(AnimationUtils.loadAnimation(mCxt, android.R.anim.slide_out_right));                    view.setAnimation(AnimationUtils.loadAnimation(mCxt, R.anim.right_in));                }            };            mViewPager.setPageTransformer(true, pageTransformer);        }    }    /**     * 获取图片集合的size     *      * @return     */    private int getSize() {        return (mImgUrls == null ? 0 : mImgUrls.size());    }    public boolean isEmpty() {        return (mImgUrls == null);    }    /**     * 开启组件     */    public void startUpAdComponent() {        currentIndex = 0;        pagerCurrent = 0;        mViewPager.setAdapter(mPagerAdapter);        mViewPager.setCurrentItem(currentIndex);        updateIndicator(currentIndex);        startTimer();    }    /**     * 更新组件中adapter数据     */    public void updateAdComponent() {        stopTimer();        resetIndicatorLayout();        mPagerAdapter.notifyDataSetChanged();        startUpAdComponent();    }    /**     * 在页面销毁的时候调用该方法     */    public void stopAdComponent() {        stopTimer();    }    /**     * 停止自动滚动的任务     */    public void stopTimer() {        timeRunning = false;        if (mTimer != null) {            mTimer.cancel();            mTimer = null;        }    }    /**     * 开始自动滚动的任务,注意,只有图片个数大于1的时候才会自动滚动     */    public void startTimer() {        timeRunning = true;        if (mTimer == null && getSize() > 1 && mSwitchTime > 0) {            mTimer = new Timer();            mTimer.schedule(new PagerTimerTask(), mSwitchTime, mSwitchTime);        }    }    private class PagerTimerTask extends TimerTask {        @Override        public void run() {            currentIndex++;            pagerCurrent++;            mHandler.sendEmptyMessage(0);        }    }    private class MyOnPageChangeListener implements OnPageChangeListener {        @Override        public void onPageScrollStateChanged(int arg0) {        }        @Override        public void onPageScrolled(int arg0, float arg1, int arg2) {        }        @Override        public void onPageSelected(int position) {            pagerCurrent = position;            currentIndex = position % getSize();// 更新当前页面            updateIndicator(currentIndex);        }    }    /**     * 更新圆点指示器     */    private void updateIndicator(int position) {        if (!isEmpty() && position < getSize()) {            if (getSize() > 1) {                resetAllIndicator(getSize());// 重置所有的指示器为为选择状态                View v = mIndicatorLayout.findViewWithTag(position);                if (v != null) {                    v.setBackgroundResource(R.drawable.circle_indicator_selected);// 点亮                }            }        }    }    /**     * 重置所有的指示器     */    private void resetAllIndicator(int size) {        if (mIndicatorLayout != null) {            for (int i = 0; i < size; i++) {                View v = mIndicatorLayout.findViewWithTag(i);                if (v != null) {                    v.setBackgroundResource(R.drawable.circle_indicator_normal);                }            }        }    }        @SuppressLint("HandlerLeak")    private Handler mHandler = new Handler() {        public void handleMessage(android.os.Message msg) {            mViewPager.setCurrentItem(pagerCurrent);        };    };}

 

当网络加载图片url列表成功之后,只需调用mAdComponent.updateAdComponent();即可

例如我的代码

 

private void updateAdSources(List<HomeBannerDTO> list) {        imageUrls.clear();        for (HomeBannerDTO dto : list) {            imageUrls.add(dto.getUrl());        }        mBannerList.clear();        mBannerList.addAll(list);        //更新banner组件        mAdComponent.updateAdComponent();        LogHelper.d(TAG, "updateAdComponent .....");        SettingsMgr.setLastRecommendAdList(mCxt, mBannerList);    }

 

广告banner:手动滑动切换,自动切换,点击跳转,异步加载网络图片