效果图:

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

代码说话:

布局文件:

<!-- 广告位 --><FrameLayoutandroid:id="@+id/new_recommend"android:layout_width="fill_parent"android:layout_height="wrap_content" ><com.cyou.cmall.ui.HorizontalViewPagerandroid:id="@+id/viewpager"android:layout_width="fill_parent"android:layout_height="fill_parent" /><LinearLayoutandroid: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());}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {boolean dispatchTouchEvent = super.dispatchTouchEvent(ev);if (dispatchTouchEvent) {if (mGestureDetector.onTouchEvent(ev)) {//请求父类放弃事件的处理requestDisallowInterceptTouchEvent(true);}}return dispatchTouchEvent;}class YScrollDetector extends SimpleOnGestureListener {@Overridepublic 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() {@Overridepublic 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();}@Overridepublic int getCount() {if (imageUrls.size() < 2) {return imageUrls.size();}return Integer.MAX_VALUE;}@Overridepublic boolean isViewFromObject(View arg0, Object arg1) {return arg0 == arg1;}@Overridepublic 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() {@Overridepublic void onLoadingStarted(String imageUri, View view) {spinner.setVisibility(View.VISIBLE);}@Overridepublic void onLoadingFailed(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);}@Overridepublic void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {spinner.setVisibility(View.GONE);}});view.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {if (mListener !=null) {mListener.OnViewPagerItemClick(index);}}});container.addView(view);return view;}@Overridepublic 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() {@Overridepublic 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 {@Overridepublic void run() {currentIndex++;pagerCurrent++;mHandler.sendEmptyMessage(0);}}private class MyOnPageChangeListener implements OnPageChangeListener {@Overridepublic void onPageScrollStateChanged(int arg0) {}@Overridepublic void onPageScrolled(int arg0, float arg1, int arg2) {}@Overridepublic 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:手动滑动切换,自动切换,点击跳转,异步加载网络图片相关推荐

  1. ViewPager(一屏多页、无限滑动、自动切换)

    一.简介 前段时间在腾讯视频中看到一个效果,是一个广告轮播,然后一屏还显示了多页.看着这个效果看着还不错,就自己实现了下. 国际惯例先上效果图,如下:(虽然界面比较简陋,但是功能是全的) ====== ...

  2. 用js实现点击切换+自动切换的轮播图

    用js实现点击切换+自动切换的轮播图 之前博主写过一篇用css实现轮播图的文章,可以看到用css实现的轮播图也能实现我们所需要的功能.那么这些功能用js该如何实现呢?我们一起来看下吧! (ps:博主在 ...

  3. Unity3D 场景切换异步加载进度

    异步加载场景分为A.B.C三个场景 A场景是开始场景:B场景是加载场景(进度条加载显示):C场景是目标场景 在A场景中添加一个按钮,触发函数: //异步加载新场景 public void LoadNe ...

  4. 切换不同的数据状态布局,包含加载中、空数据和出错状态,可自定义状态布局

    代码地址如下: http://www.demodashi.com/demo/12318.html StatusLayoutManager 切换不同的数据状态布局,包含加载中.空数据和出错状态. git ...

  5. 一步步手动实现热修复(一)-dex文件的生成与加载

    *本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 热修复技术自从QQ空间团队搞出来之后便渐渐趋于成熟. 我们这个系列主要介绍如何一步步手动实现基本的热修复功能,无需使用第三方框架. ...

  6. 百度ssp php源码,百度联盟SSP媒体广告异步加载代码最优解决方案

    百度联盟SSP媒体广告异步加载代码最优解决方案 相信很多站长跟我一样,建站之后第一时间就会去做百度.谷歌等联盟广告,原因很简单,就是希望能给自己增加一丢丢的收入,虽然可能几个月才收到100块(百度真小 ...

  7. 百度联盟广告代码php,js 投放联盟广告代码可异步加载百度联盟广告

    js 投放联盟广告代码一般方法介绍,普通的加载方式容易阻塞页面加载,所以我们使用异步加载百度联盟广告代码,广告js代码就可以异步加载无阻塞 如果你有一个网站或者个人博客,想投放百度联盟广告代码以获取收 ...

  8. 百度联盟广告代码php,百度联盟广告异步加载的方法

    百度联盟广告很多个人站长都在用 ,虽说不指望靠它挣大钱 ,但是补贴下域名服务器费用也是极好的. simon最近一直在尝试优化页面载入速度,好提升用户体验,但后来发现只要加载了百度联盟的广告,页面加载时 ...

  9. google android广告异步加载,javascript 广告后加载,加载完页面再加载广告

    先加载完页面再加载广告的原理: 网页打开的顺序都是按页面从上到下的顺序加载完成的,所以要想使广告不影响页面打开速度,就要等页面全部打开完成后,再加载JS代码.等页面加载完再加载广告其实就是将广告的 J ...

最新文章

  1. vue2.0组件生命周期探讨
  2. 7-3 jmu-Java-06异常-03-throw与throws (10 分)
  3. mysql 回表查询优化_MySQL中的回表查询与索引覆盖:一次百万级别分页查询使用Limit 从90秒到0.6毫秒的优化...
  4. linux 的date命令详解,linux之date命令详解
  5. 4邻接、8邻接、m邻接
  6. c++语言怎么从internet上某个时间服务器获取时间信息,在VC++中实现同步Internet时间...
  7. 蓝桥杯2021年第十二届C++省赛第九题-双向排序
  8. 电脑怎么打出冒号符号_标点符号的用法,资深老师带你学习,提高学生学习效率...
  9. python定位元素方法_Python+webdriver定位元素的几种方法
  10. C语言中access/_access函数的使用
  11. 云流化像素流技术解决方案之虚拟仿真系统
  12. SSTV 建伍TK8185 连接电脑
  13. linux怎么进入文件的末尾,如何在Linux中附加到文件的末尾
  14. 【云计算】2_云服务器产品介绍
  15. 用Python玩转PDF的各种骚操作
  16. 我又被开了?测试工程师核心竞争力几个方面,反之是你开的“他“......
  17. kaldi教程_Kaldi语音识别快速入门
  18. 完成用户注册之后,跳转到用户注册的邮箱所在的网址
  19. matlab 结构张量,图像处理中的结构张量(structure tensor)
  20. Tina R16开发说明

热门文章

  1. android 6.0权限
  2. opencv多线程显示的问题和解决方法
  3. 解决:object_detection/protos/*.proto: Invalid argument.
  4. OpenCV图像剪切的扩展和高级用法:任意裁剪,边界扩充
  5. ELK技术栈—Kibana
  6. 分布式文件系统—HDFS—IDEA的Hadoop可视化插件BigDataTools
  7. 编程之美 set 1 不要被阶乘吓倒
  8. ubuntu系统下gedit 打开GBK字符集编码文件出现乱码问题解决办法
  9. 关于ibatis.net 和 Nhibernate的选择
  10. .net 深入系统编程(三)