使用BannerView做无限轮播

之前在做无限轮播的时候一直在使用ViewPager可能是我比较守旧的缘故吧,一直到这几天又要实现此项功能了,听朋友说BannerView特别好用并且是真正意义上的无限轮播,再也不是之前的Integer.MAX了,感觉挺好的所以就拿来研究了一下,实现了这个功能,可能会有些凌乱的地方,仅供大家参考,如果大家有什么好的建议可以给我留言我一定改正。

不多说了直接上代码大笑


首先是布局


<com.chenantao.autolayout.AutoRelativeLayout
    android:id="@+id/find_all_viewpager"
    android:layout_width="match_parent"
    android:layout_height="550px"
    >

    <ImageView
        android:id="@+id/main_cycleView_Img"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:scaleType="fitXY"
        android:src="@mipmap/bannerdefault"
        android:visibility="visible" />

    <com.innospace.view.ImageCycleView
        android:id="@+id/find_cycleView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />
    <LinearLayout
        android:id="@+id/all_dots"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@id/main_cycleView_Img"
        android:layout_marginBottom="10dp"
        android:gravity="center"
        android:orientation="horizontal"></LinearLayout>

    

</com.chenantao.autolayout.AutoRelativeLayout>


然后我只贴出与实现此功能相关的大家能用到的代码,有些代码因项目不同贴出来也不见得能用,所以还需大家自行编写。

首先就是网络请求数据,这个不进行张贴,各项目有所不同,拿到数据后将数据传递到Handler 进行更新UI的操作,下面是Handler中要实现的代码



bannerList.clear();
bannerList.addAll(list);
find_cycleView.setImageResources(bannerList, mAdCycleViewListener);
if (list != null && list.size() != 0) {
    nodata_banaImg.setVisibility(View.GONE);
    find_cycleView.setVisibility(View.VISIBLE);
} else {
    nodata_banaImg.setVisibility(View.VISIBLE);
    find_cycleView.setVisibility(View.GONE);
}


代码很简单,无非就是控制该控件的显示和隐藏罢了,这里不做过多的解释,但是注意

find_cycleView.setImageResources(bannerList, mAdCycleViewListener);
代码中 mAdCycleViewListener  这个下面马上张贴出来


ImageCycleView.ImageCycleViewListener mAdCycleViewListener = new ImageCycleView.ImageCycleViewListener() {

    @Override
    public void onImageClick(BannerDao info, int postion, View imageView) {
        if (!isNetworkConnected()) {
            if (toast == null) {
                toast = Toast
                        .makeText(context, "网络不可用", Toast.LENGTH_SHORT);
            } else {
                toast.cancel();// 关闭吐司显示
                toast = Toast
                        .makeText(context, "网络不可用", Toast.LENGTH_SHORT);
            }
            toast.show();
        } else {
            Intent intent = new Intent(context, ActionDetailActivity.class);
            MyLog.e(context, "BannarDao:" + info.toString());
            MyLog.e(context, "id:" + info.getRelatedId());
            id = info.getRelatedId();
            int jumpType = 0;
            intent.putExtra("id", info.getRelatedId() + "");
            intent.putExtra("index", "1");
            intent.putExtra("type", info.getType());
            intent.putExtra("title", info.getTitle());
            intent.putExtra("picPath", info.getPicPath());
            // intent.putExtra("url", info.getUrl());
            System.out.println("要传递的banner类型是::" + info.getType());
            intent.putExtra("jumpType", jumpType);
            if (info.getUrl() != null && !info.getUrl().equals("")) {
                intent.putExtra("url", info.getUrl());
            }
            startActivity(intent);
        }
    }

    @Override
    public void displayImage(String imageURL, ImageView imageView) {
        ImageListener imageListener = ImageLoader.getImageListener(
                imageView, R.mipmap.bannerdefault,
                R.mipmap.bannerdefault);
        mImageLoader.get(imageURL, imageListener);

    }
};

这里的代码由于项目需要写的太乱,还有好多是在打印Log也没有进行删除,大家将就着看看,功能能够实现才是最重要的。


下面最重要的代码来了,为了让大家看清我把这个类中所有的代码全都贴出来:


/**
 * 广告图片自动轮播控件</br>
 * 
 * <pre>
 *   集合ViewPager和指示器的一个轮播控件,主要用于一般常见的广告图片轮播,具有自动轮播和手动轮播功能 
 *   使用:只需在xml文件中使用{@code <com.minking.imagecycleview.ImageCycleView/>} ,
 *   然后在页面中调用  {@link #setImageResources(ArrayList, ImageCycleViewListener) }即可!
 *   
 *   另外提供{@link #startImageCycle() } \ {@link #pushImageCycle() }两种方法,用于在Activity不可见之时节省资源;
 *   因为自动轮播需要进行控制,有利于内存管理
 * </pre>
 * 
 */
public class ImageCycleView extends LinearLayout {

   /**
    * 上下文
    */
   private Context mContext;

   /**
    * 图片轮播视图
    */
   private CycleViewPager mBannerPager = null;

   /**
    * 滚动图片视图适配器
    */
   private ImageCycleAdapter mAdvAdapter;

   /**
    * 图片轮播指示器控件
    */
   private ViewGroup mGroup;

   /**
    * 图片轮播指示器-个图
    */
   private ImageView mImageView = null;

   /**
    * 滚动图片指示器-视图列表
    */
   private ImageView[] mImageViews = null;

   /**
    * 图片滚动当前图片下标
    */
   private int mImageIndex = 1;

   /**
    * 手机密度
    */
   private float mScale;

   /**
    * @param context
    */
   public ImageCycleView(Context context) {
      super(context);
   }

   /**
    * @param context
    * @param attrs
    */
   public ImageCycleView(Context context, AttributeSet attrs) {
      super(context, attrs);
      mContext = context;
      mScale = context.getResources().getDisplayMetrics().density;
      LayoutInflater.from(context)
            .inflate(R.layout.view_banner_content, this);
      mBannerPager = (CycleViewPager) findViewById(R.id.pager_banner);
      mBannerPager.setOnPageChangeListener(new GuidePageChangeListener());
      mBannerPager.setOnTouchListener(new OnTouchListener() {

         @Override
         public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
            case MotionEvent.ACTION_UP:
               // 开始图片滚动
               startImageTimerTask();
               break;
            default:
               // 停止图片滚动
               stopImageTimerTask();
               break;
            }
            return false;
         }
      });
      // 滚动图片右下指示器视图
      mGroup = (ViewGroup) findViewById(R.id.viewGroup);
   }

   /**
    * 装填图片数据
    * imageUrlList
    * @param
    * @param imageCycleViewListener
    */
   public void setImageResources(ArrayList<BannerDao> infoList,
         ImageCycleViewListener imageCycleViewListener) {
      // 清除所有子视图
      mGroup.removeAllViews();
      // 图片广告数量
      // final int imageCount = infoList.size();
      final int imageCount = infoList.size();
      mImageViews = new ImageView[imageCount];
      for (int i = 0; i < imageCount; i++) {
         mImageView = new ImageView(mContext);
         int imageParams = (int) (mScale * 7);// XP与DP转换,适应不同分辨率
         int imagePadding = (int) (mScale * 2.5);
         LayoutParams layout = new LayoutParams(
               imageParams, imageParams);
         layout.setMargins(imagePadding, 0, imagePadding, 0);
         mImageView.setLayoutParams(layout);
         mImageViews[i] = mImageView;
         if (i == 0) {
            mImageViews[i].setBackgroundResource(R.drawable.point_focused);
         } else {
            mImageViews[i]
                  .setBackgroundResource(R.drawable.point_unfocused);
         }
         mGroup.addView(mImageViews[i]);
      }
      mAdvAdapter = new ImageCycleAdapter(mContext, infoList,
            imageCycleViewListener);
      mBannerPager.setAdapter(mAdvAdapter);
      startImageTimerTask();
   }

   /**
    * 开始轮播(手动控制自动轮播与否,便于资源控制)
    */
   public void startImageCycle() {
      startImageTimerTask();
   }

   /**
    * 暂停轮播——用于节省资源
    */
   public void pushImageCycle() {
      stopImageTimerTask();
   }

   /**
    * 开始图片滚动任务
    */
   private void startImageTimerTask() {
      stopImageTimerTask();
      // 图片每3秒滚动一次
      mHandler.postDelayed(mImageTimerTask, 3000);
   }

   /**
    * 停止图片滚动任务
    */
   private void stopImageTimerTask() {
      mHandler.removeCallbacks(mImageTimerTask);
   }

   private Handler mHandler = new Handler();

   /**
    * 图片自动轮播Task
    */
   private Runnable mImageTimerTask = new Runnable() {

      @Override
      public void run() {
         if (mImageViews != null) {
            // 下标等于图片列表长度说明已滚动到最后一张图片,重置下标
            if ((mImageIndex++) == mImageViews.length+1) {
               mImageIndex = 1;
            }
            mBannerPager.setCurrentItem(mImageIndex);
         }
      }
   };

   /**
    * 轮播图片状态监听器
    * 
    * @author minking
    */
   private final class GuidePageChangeListener implements OnPageChangeListener {

      @Override
      public void onPageScrollStateChanged(int state) {
         if (state == ViewPager.SCROLL_STATE_IDLE)
            startImageTimerTask(); // 开始下次计时
      }

      @Override
      public void onPageScrolled(int arg0, float arg1, int arg2) {
      }

      @Override
      public void onPageSelected(int index) {

         if (index == 0 || index == mImageViews.length + 1) {
            return;
         }
         // 设置图片滚动指示器背景
         mImageIndex = index;
         index -= 1;
         mImageViews[index].setBackgroundResource(R.drawable.point_focused);
         for (int i = 0; i < mImageViews.length; i++) {
            if (index != i) {
               mImageViews[i]
                     .setBackgroundResource(R.drawable.point_unfocused);
            }
         }
      }
   }

   private class ImageCycleAdapter extends PagerAdapter {

      /**
       * 图片视图缓存列表
       */
      private ArrayList<ImageView> mImageViewCacheList;

      /**
       * 图片资源列表
       */
      private ArrayList<BannerDao> mAdList = new ArrayList<BannerDao>();

      /**
       * 广告图片点击监听器
       */
      private ImageCycleViewListener mImageCycleViewListener;

      private Context mContext;

      public ImageCycleAdapter(Context context, ArrayList<BannerDao> adList,
            ImageCycleViewListener imageCycleViewListener) {
         mContext = context;
         mAdList = adList;
         mImageCycleViewListener = imageCycleViewListener;
         mImageViewCacheList = new ArrayList<ImageView>();
      }

      @Override
      public int getCount() {
         return mAdList.size();
      }

      @Override
      public boolean isViewFromObject(View view, Object obj) {
         return view == obj;
      }

      @Override
      public Object instantiateItem(ViewGroup container, final int position) {
         String imageUrl = mAdList.get(position).getPicPath();
         ImageView imageView = null;
         if (mImageViewCacheList.isEmpty()) {
            imageView = new ImageView(mContext);
            imageView.setLayoutParams(new LayoutParams(
                  LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
            imageView.setScaleType(ImageView.ScaleType.FIT_XY);

         } else {
            imageView = mImageViewCacheList.remove(0);
         }
         // 设置图片点击监听
         imageView.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
               System.out.println("这里点击的图片的游标是::"
                     + mAdList.get(position).getRelatedId());
               System.out.println("图片集合的长度是是::" + mAdList.size());
               mImageCycleViewListener.onImageClick(mAdList.get(position),
                     position, v);
            }
         });
         imageView.setTag(imageUrl);
         container.addView(imageView);
         mImageCycleViewListener.displayImage(imageUrl, imageView);
         return imageView;
      }

      @Override
      public void destroyItem(ViewGroup container, int position, Object object) {
         ImageView view = (ImageView) object;
         container.removeView(view);
         mImageViewCacheList.add(view);
      }
   }

   /**
    * 轮播控件的监听事件
    * 
    * @author minking
    */
   public static interface ImageCycleViewListener {

      /**
       * 加载图片资源
       * 
       * @param imageURL
       * @param imageView
       */
      public void displayImage(String imageURL, ImageView imageView);

      /**
       * 单击图片事件
       * position
       * @param
       * @param imageView
       */
      public void onImageClick(BannerDao info, int postion, View imageView);
   }

}


这里有必要说一下,我在实现轮播的时候出现了这样一个问题,就是在几张图片完整的轮播一遍之后会有快速显示所有图片然后才去加载第一张的现象(Bug),不过大家不用担心,这个代码是改好了的,现在我就来说一说我改动的地方,在大概195行的位置(哦,sorry这貌似没有行标),不过没关系好在我有注释,是图片自动轮播Task中这几行代码


if((mImageViews++)==mImageViews.length+1){

           mImageIndex=1;

}

在这几行中之前的代码是++mImageViews,所以出现了上述情况,虽然现在解决了但是至今我也不太清楚为什么要这么改,如果有知道的童鞋希望大家给我留言哈吐舌头,好了今天就先写到这里吧,以后有什么值得分享的一定还会贴出来的。



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
现在的APP Banner大多数千篇一律,前几天看到魅族手机上所有魅族自家APP上的Banner效果不错,于是就想着来仿着一个类似的效果。因此就有了这个库。但是为了使用方便,这个库不仅仅只有仿魅族效果的BannerView使用,还可以当作普通的BannerView使用,还可以当作一个ViewPager 来使用使用很方便,具体使用方法和API 请看后面的示例。 ---  左图为魅族APP上的Banner效果,右图是高仿效果。MZBannerView 有以下功能:1 . 仿魅族BannerView 效果。2 . 当普通Banner 使用3 . 当普通ViewPager 使用。4 . 当普通ViewPager使用(有魅族Banner效果)5 . 仿某视频网站Banner效果。Demo APKgif图片有点模糊,可以扫描下方二维码下载APK体验相关博客ViewPager系列之 仿魅族应用的广告BannerView更新日志v1.1.1 : 增加按住Banner 停止轮播,松开开始自动轮播的功能v1.1.0 : fix 在从网上获取数据后,banner 显示 造成 ANR 的bug(如果在onCreate()中设置资源显示则没问题)v1.1.2 : fix 更改数据之后,调用setPages重新刷新数据会crush的bugv2.0.0 :1,add: 添加仿魅族Banner效果,中间Page覆盖两边。 -- 2,fix 部分bug: 添加OnPageChangeListener 回调 pisition 不对的bug.DependencyAdd it in your root build.gradle at the end of repositories:allprojects {      repositories {           ...           maven { url 'https://jitpack.io' }      } }Step 2. Add the dependencydependencies {          compile 'com.github.pinguo-zhouwei:MZBannerView:v2.0.0' }自定义属性属性名属性意义取值open_mz_mode是否开启魅族模式true 为魅族Banner效果,false 则普通Banner效果canLoop是否轮播true 轮播,false 则为普通ViewPagerindicatorPaddingLeft设置指示器距离左侧的距离单位为 dp 的值indicatorPaddingRight设置指示器距离右侧的距离单位为 dp 的值indicatorAlign设置指示器的位置有三个取值:left 左边,center 剧中显示,right 右侧显示middle_page_cover设置中间Page是否覆盖(真正的魅族Banner效果)true 覆盖,false 无覆盖效果使用方法1 . xml 布局文件2 . activity中代码:mMZBanner = (MZBannerViewview.findViewById(R.id.banner);              // 设置数据         mMZBanner.setPages(list, new MZHolderCreator() {             @Override             public BannerViewHolder createViewHolder() {                 return new BannerViewHolder();             }         });  public static class BannerViewHolder implements MZViewHolder {         private ImageView mImageView;         @Override         public View createView(Context cont
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值