Android自定义banner轮播控件,可以扩展条形或者圆点指示器效果

运行效果如下,这里展示的是条形指示器的效果,你可以改成圆点形式的也: 

                                                              不好意思视频转gif图的时候翻转角度出问题了 

自定义banner控件BannerView:

/**
 * Created by wjj on 18/12/20 20:40
 * [email protected]
 * 自定义无限轮播banner控件
 */
public class BannerView extends RelativeLayout implements BannerAdapter.ViewPagerOnItemClickListener {
  ViewPager viewPager;
  LinearLayout points;
  //默认轮播时间,3s
  private int delayTime = 3000;
  private List<ImageView> imageViewList;
  private List<HomeDataBeanF.Data.New_wallpaper.New_wallpaper_list> bannerList;
  //选中显示Indicator 小圆点样式
//  private int selectRes = R.drawable.shape_dots_select;
  //条形指示器样式
  private int selectRes = R.drawable.shape_line_select;
  //非选中显示Indicator
//  private int unSelcetRes = R.drawable.shape_dots_default;
  private int unSelcetRes = R.drawable.shape_line_default;
  //当前页的下标
  private int currentPos;

  private Handler handler ;


  public ViewPager getViewPager() {
    return viewPager;
  }

  public BannerView(Context context) {
    this(context, null);
    initView();
  }


  public BannerView(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
    initView();
  }

  public BannerView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    LayoutInflater.from(getContext()).inflate(R.layout.layout_custom_banner, this, true);
    imageViewList = new ArrayList<>();
    initView();
  }

  private void initView() {
    viewPager = findViewById(R.id.layout_banner_viewpager);
    points = findViewById(R.id.layout_banner_points_group);
  }


  /**
   * 设置轮播间隔时间
   *
   * @param time 轮播间隔时间,单位秒
   */
  public BannerView delayTime(int time) {
    this.delayTime = time;
    return this;
  }


  /**
   * 设置Points资源 Res
   *
   * @param selectRes 选中状态
   * @param unselcetRes 非选中状态
   */
  public void setPointsRes(int selectRes, int unselcetRes) {
    this.selectRes = selectRes;
    this.unSelcetRes = unselcetRes;
  }


  /**
   * 图片轮播需要传入参数
   */
  public void build(List<HomeDataBeanF.Data.New_wallpaper.New_wallpaper_list> list) {
    destroy();
    if (list.size() == 0) {
      this.setVisibility(GONE);
      return;
    }
    bannerList = new ArrayList<>();
    bannerList.addAll(list);
    final int pointSize;
    pointSize = bannerList.size();
    if (pointSize == 2) {
      bannerList.addAll(list);
    }
    //判断是否清空 指示器点
    if (points.getChildCount() != 0) {
      points.removeAllViewsInLayout();
    }
    //初始化与个数相同的指示器点
    for (int i = 0; i < pointSize; i++) {
      View dot = new View(getContext());
      dot.setBackgroundResource(unSelcetRes);
      LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
//          DipDpUtil.dip2px(getContext(), 5),
//              DipDpUtil.dip2px(getContext(), 5));
          DipDpUtil.dip2px(getContext(), 13),
              DipDpUtil.dip2px(getContext(), 2));
      params.leftMargin = DipDpUtil.dip2px(getContext(), 4);
      dot.setLayoutParams(params);
      dot.setEnabled(false);
      points.addView(dot);
    }
    points.getChildAt(0).setBackgroundResource(selectRes);
    for (int i = 0; i < bannerList.size(); i++) {
      ImageView mImageView = new ImageView(getContext());
      mImageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
      LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(
              LinearLayout.LayoutParams.MATCH_PARENT,
              LinearLayout.LayoutParams.MATCH_PARENT
      );
      mImageView.setLayoutParams(p);
      if(!StringUtils.StringIsNull(bannerList.get(i).getWurl_preview())){
        mImageView.setImageResource(R.drawable.home_top_loadpic);
      }else {

        Glide.with(getContext())
                .load(bannerList.get(i).getWurl_middle())
                .apply(RequestOptions
                .bitmapTransform(new GlideRoundTransform2(getContext(),8))
                .placeholder(R.drawable.home_top_loadpic)
                .error(R.drawable.home_top_loadpic)
                .diskCacheStrategy(DiskCacheStrategy.ALL))
                .into(mImageView);
        Log.d("bannerview","--url"+bannerList.get(i).getWurl_preview());
      }

      imageViewList.add(mImageView);
    }
    //监听图片轮播,改变指示器状态
    viewPager.clearOnPageChangeListeners();
    viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
      @Override
      public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}

      @Override
      public void onPageSelected(int pos) {
        pos = pos % pointSize;
        currentPos = pos;
        for (int i = 0; i < points.getChildCount(); i++) {
          points.getChildAt(i).setBackgroundResource(unSelcetRes);
        }
        points.getChildAt(pos).setBackgroundResource(selectRes);
      }

      @Override
      public void onPageScrollStateChanged(int state) {
        switch (state) {
          // 闲置中
          case ViewPager.SCROLL_STATE_IDLE:
            isAutoPlay = true;
            break;
          // 拖动中
          case ViewPager.SCROLL_STATE_DRAGGING:
            isAutoPlay = false;
            break;
          // 设置中
          case ViewPager.SCROLL_STATE_SETTLING:
            isAutoPlay = true;
            break;
        }
      }
    });

    BannerAdapter bannerAdapter = new BannerAdapter(imageViewList);
    viewPager.setAdapter(bannerAdapter);
    bannerAdapter.notifyDataSetChanged();
    bannerAdapter.setmViewPagerOnItemClickListener(this);
    //图片开始轮播
    startScroll();
  }

  private boolean isAutoPlay = false;


  /**
   * 图片开始轮播
   */
  private void startScroll() {
    // 如果少于2张就不用自动播放了
    if (bannerList.size() < 2) {
      isAutoPlay = false;
    } else {
      isAutoPlay = true;
      handler = new Handler();
      handler.postDelayed(task, delayTime);
    }
  }


  private Runnable task = new Runnable() {
    @Override
    public void run() {
      if (isAutoPlay) {
        // 正常每隔3秒播放一张图片
        viewPager.setCurrentItem(viewPager.getCurrentItem() + 1);
//        vpImageTitle.setCurrentItem(currentItem);
        handler.postDelayed(task, 3000);
      } else {
        // 如果处于拖拽状态停止自动播放,会每隔5秒检查一次是否可以正常自动播放。
        handler.postDelayed(task, 5000);
      }
    }
  };



  public void destroy() {
  }


  /**
   * 设置ViewPager的Item点击回调事件
   */
//  @Override
//  public void onItemClick(int positon) {

//    BrowserActivity.launch((Activity) getContext(),
//        bannerList.get(currentPos).link,
//        bannerList.get(currentPos).title);

//  }


  /**
   * 设置ViewPager的Item点击回调事件
   */
  @Override
  public void onBannerItemClick(int possition) {

    Intent intent = new Intent(getContext(), WallpaperListActivity.class);
    intent.putExtra("isVideo", false);
    intent.putExtra("category", "new");
    getContext().startActivity(intent);

    //如果有特殊需求可以从外面回调点击事件接口
//    MainActivity.banneritemlistener.onBannerItemClick(possition);
  }
}

bannerview的布局代码:
 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

        <android.support.v4.view.ViewPager
            android:id="@+id/layout_banner_viewpager"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_113"
        android:layout_alignParentBottom="true"
        android:scaleType="fitXY"
        android:src="@drawable/newwallpaper_rectangle" />

    <LinearLayout
        android:id="@+id/layout_banner_points_group"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@id/layout_banner_viewpager"
        android:layout_alignParentRight="true"
        android:layout_marginBottom="@dimen/dp_10"
        android:layout_marginRight="@dimen/dp_15"
        android:orientation="horizontal"
        android:visibility="visible" />

    <!--android:layout_centerHorizontal="true"-->
    <!--想让指示器布居中时使用-->

</RelativeLayout>

轮播指示器是圆点的drawable文件,放在res的drawable目录下:

没有选中的时候:shape_dots_default.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">

    <solid android:color="@android:color/darker_gray" />

</shape>

选中的时候:shape_dots_select.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">

    <solid android:color="@color/white" />

</shape>

轮播指示器是条形的drawable文件,放在res的drawable目录下:

没有选中的时候:shape_line_default.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <solid android:color="#80ffffff" />

</shape>

选中的时候:shape_line_select.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <solid android:color="@color/white" />

</shape>

轮播控件的适配器:

/**
 * Created by wjj on 18/12/20 20:40
 * [email protected]
 * Banner适配器
 */
public class BannerAdapter extends PagerAdapter {
    private List<ImageView> mList;
    private int pos;
    private ViewPagerOnItemClickListener mViewPagerOnItemClickListener;

    void setmViewPagerOnItemClickListener(ViewPagerOnItemClickListener mViewPagerOnItemClickListener) {
        this.mViewPagerOnItemClickListener = mViewPagerOnItemClickListener;
    }

    BannerAdapter(List<ImageView> list) {
        this.mList = list;
    }

    @Override
    public int getCount() {
        return Integer.MAX_VALUE;
    }

    @Override
    public boolean isViewFromObject(View arg0, Object arg1) {
        return arg0 == arg1;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        int position1 = position;
        //对ViewPager页号求模取出View列表中要显示的项
        position %= mList.size();
        if (position < 0) {
            position = mList.size() + position;
        }
        ImageView v = mList.get(position);
        pos = position;
        v.setScaleType(ImageView.ScaleType.CENTER_CROP);
        LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.MATCH_PARENT,
                LinearLayout.LayoutParams.MATCH_PARENT
        );
        v.setLayoutParams(p);
        //如果View已经在之前添加到了一个父组件,则必须先remove,否则会抛出IllegalStateException。
        ViewParent vp = v.getParent();
        if (vp != null) {
            ViewGroup parent = (ViewGroup) vp;
            parent.removeView(v);
        }
        v.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mViewPagerOnItemClickListener != null) {
//                mViewPagerOnItemClickListener.onBannerItemClick(pos);
                    //发生点击banner的item后position错误异常
                    if (pos ==0){
                        pos =mList.size()-1;
                    }else {
                        pos =pos-1;
                    }
                    mViewPagerOnItemClickListener.onBannerItemClick(pos);
                }
            }
        });
        container.addView(v);
        return v;
    }


    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
    }


    public interface ViewPagerOnItemClickListener {
        void onBannerItemClick(int possition);
    }
}

使用的时候效果如下:

banner.delayTime(3000).build(bean!!.data.new_wallpaper.new_wallpaper_list)

以上是我做完项目后稍微整理出来的注释和源码,如果你在使用中遇到了什么问题或者是我忘记少贴了哪些东西,可以留言给我,我看到后会尽快回复,解决,带来不便之处还望理解!谢谢!

发布了89 篇原创文章 · 获赞 231 · 访问量 62万+

猜你喜欢

转载自blog.csdn.net/wjj1996825/article/details/85138961