欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android仿京东淘宝自动无限循环轮播控件思路详解

程序员文章站 2022-06-08 17:42:49
在app的开发中,很多的时候都需要实现类似京东淘宝一样的自动无限轮播的广告栏,所以就自己写了一个,下面是我自定义控件的思路和过程。 一、自定义控件属性 新建自定义控件s...

在app的开发中,很多的时候都需要实现类似京东淘宝一样的自动无限轮播的广告栏,所以就自己写了一个,下面是我自定义控件的思路和过程。

一、自定义控件属性

新建自定义控件sliderlayout继承于relativelayout,首先要考虑的就是自定义的控件需要扩展那些属性,把这些属性列出来。在这里是要实现类似于京东淘宝的无限轮播广告栏,那么首先想到的就是轮播的时长、轮播指示器的样式等等。我在这里列举了一些并且结合到了代码中。

1、扩展属性

(1)是否开启自动轮播的功能。
(2)指示器的图形样式,一般为圆形和方形两种。
(3)指示器的位置,一般为底部或者顶部。
(4)指示器被选中和不被选中时的样式:颜色、高度、宽度、间隔等。
(5)轮播的时长。
(6)加载的如果是网络图片的话,需要默认图片和错误图片等。

2、在attrs.xml文件中添加这些扩展的属性。

<declare-styleable name="sliderlayout">
  <attr name="sl_is_auto_play" format="boolean"/>
  <attr name="sl_indicator_shape" format="enum">
   <enum name="oval" value="0" />
   <enum name="rect" value="1" />
  </attr>
  <attr name="sl_indicator_position" format="enum">
   <enum name="centerbottom" value="0" />
   <enum name="rightbottom" value="1" />
   <enum name="leftbottom" value="2" />
   <enum name="centertop" value="3" />
   <enum name="righttop" value="4" />
   <enum name="lefttop" value="5" />
  </attr>
  <attr name="sl_selected_indicator_color" format="color|reference" />
  <attr name="sl_unselected_indicator_color" format="color|reference" />
  <attr name="sl_selected_indicator_height" format="dimension|reference" />
  <attr name="sl_selected_indicator_width" format="dimension|reference" />
  <attr name="sl_unselected_indicator_height" format="dimension|reference" />
  <attr name="sl_unselected_indicator_width" format="dimension|reference" />
  <attr name="sl_indicator_space" format="dimension|reference" />
  <attr name="sl_indicator_margin" format="dimension|reference" />
  <attr name="sl_auto_play_duration" format="integer|reference" />
  <attr name="sl_default_image" format="reference"/>
  <attr name="sl_error_image" format="reference"/>
 </declare-styleable>

二、自定义轮播控件的初始化

1、获取到扩展属性的值

在自定义sliderlayout中获取到扩展的样式,然后根据样式获取相应的属性值,最好是要先设置好默认值。

typedarray array = context.obtainstyledattributes(attrs, r.styleable.sliderlayout, defstyleattr, 0);
  if (array != null) {
   isautoplay = array.getboolean(r.styleable.sliderlayout_sl_is_auto_play, isautoplay);
   //get the shape of indicator
   int intshape = array.getint(r.styleable.sliderlayout_sl_indicator_shape, indicatorshape.ordinal());
   for (indicatorshape shape : indicatorshape.values()) {
    if (shape.ordinal() == intshape) {
     indicatorshape = shape;
     break;
    }
   }
   //get the position of indicator
   int intposition = array.getint(r.styleable.sliderlayout_sl_indicator_position, indicatorposition.centerbottom.ordinal());
   for (indicatorposition position : indicatorposition.values()) {
    if (position.ordinal() == intposition) {
     indicatorposition = position;
     break;
    }
   }
   unselectedindicatorcolor = array.getcolor(r.styleable.sliderlayout_sl_unselected_indicator_color, unselectedindicatorcolor);
   selectedindicatorcolor = array.getcolor(r.styleable.sliderlayout_sl_selected_indicator_color, selectedindicatorcolor);
   unselectedindicatorheight = array.getdimension(r.styleable.sliderlayout_sl_unselected_indicator_height, unselectedindicatorheight);
   unselectedindicatorwidth = array.getdimension(r.styleable.sliderlayout_sl_unselected_indicator_width, unselectedindicatorwidth);
   selectedindicatorheight = array.getdimension(r.styleable.sliderlayout_sl_selected_indicator_height, selectedindicatorheight);
   selectedindicatorwidth = array.getdimension(r.styleable.sliderlayout_sl_selected_indicator_width, selectedindicatorwidth);
   indicatorspace = array.getdimension(r.styleable.sliderlayout_sl_indicator_space, indicatorspace);
   indicatormargin = array.getdimension(r.styleable.sliderlayout_sl_indicator_margin, indicatormargin);
   autoplayduration = array.getint(r.styleable.sliderlayout_sl_auto_play_duration, autoplayduration);
   defaultimage = array.getresourceid(r.styleable.sliderlayout_sl_default_image, defaultimage);
   errorimage = array.getresourceid(r.styleable.sliderlayout_sl_error_image, errorimage);
  }

2、初始化控件

根据这里所需要实现的功能,首先需要一个图像切换器imageswticher,还要指示器,这里就用imageview了。

switcherimage = new imageswitcher(context);
  switcherimage.setlayoutparams(new layoutparams(layoutparams.match_parent, layoutparams.match_parent));
for (int i = 0; i < itemcount; i++) {
   imageview indicator = new imageview(context);
   indicator.setlayoutparams(new viewgroup.layoutparams(viewgroup.layoutparams.wrap_content, viewgroup.layoutparams.wrap_content));
   indicator.setpadding((int) (indicatorspace), (int) (indicatorspace), (int) (indicatorspace), (int) (indicatorspace));
   indicator.setimagedrawable(unselecteddrawable);
   indicatorcontainer.addview(indicator);
   final int finali = i;
   indicator.setonclicklistener(new onclicklistener() {
    @override
    public void onclick(view view) {
     stopautoplay();
     switchindicator(finali);
     pictureindex = finali;
     handler.sendemptymessagedelayed(start_auto_play,autoplayduration);
    }
   });
  }

3、初始化选中第一张图片

专门写一个针对指示器切换的函数,然后在初始化的时候直接调用,选中第一个指示器,就是选中第一张图片了。

函数代码如下。

private void switchindicator(int index) {
  for (int i = 0; i < indicatorcontainer.getchildcount(); i++) {
   ((imageview) indicatorcontainer.getchildat(i)).setimagedrawable(i == index ? selecteddrawable : unselecteddrawable);
  }
  loadimage(index);
 }

调用选中第一张图。

switchindicator(0);

三、图片的加载

1、网路图片的加载

在这里使用picasso框架来加载图片,根据url来加载显示图片,同时也要显示图片的加载进度,这里就需要一个dialog提示框了,dialog的样式最好是可以自定义的。

private void loadnetimage(int pictureindex) {
  if (list != null && list.size() != 0) {
   picasso.with(context)
     .load((string) list.get(pictureindex))
     .placeholder(defaultimage)
     .error(errorimage)
     .tag(context)
     .into(mtarget);
  }
 }

下面是图片的加载提示过程。

private target mtarget = new target() {
  @override
  public void onbitmaploaded(bitmap bitmap, picasso.loadedfrom from) {
   dismissdialog();
   ((imageview) switcherimage.getcurrentview()).setscaletype(imageview.scaletype.center_crop);
   ((imageview) switcherimage.getcurrentview()).setlayoutparams(new imageswitcher.layoutparams(imageswitcher.layoutparams.match_parent, imageswitcher.layoutparams.match_parent));
   ((imageview) switcherimage.getcurrentview()).setimagebitmap(bitmap);
  }
  @override
  public void onbitmapfailed(drawable errordrawable) {
   dismissdialog();
   ((imageview) switcherimage.getcurrentview()).setimagedrawable(errordrawable);
  }
  @override
  public void onprepareload(drawable placeholderdrawable) {
   showdialog();
  }
 };

2、资源图片的加载

只能加载网络图片是不够的呢,还需要可以加载资源图片,加载资源图片的办法就更加简单了。

private void loadfileimage(int pictureindex) {
   if (list != null && list.size() != 0) {
    switcherimage.setimageresource((integer) list.get(pictureindex));
   }
  }

四、设置图片切换的动画

设置图片从左往右以及从右往左的动画效果,并且当滑动到该图片时,指示器也要一起变化,这里就简单说下从左往右的动画了。

private void sliderlefttoright() {
  // get current index
  pictureindex = pictureindex == 0 ? itemcount - 1
    : pictureindex - 1;
  // set animation
  switcherimage.setinanimation(animationutils.loadanimation(context,
    android.r.anim.slide_in_left));
  switcherimage.setoutanimation(animationutils.loadanimation(context,
    android.r.anim.slide_out_right));
  switchindicator(pictureindex);
 }

从右往左滑动时的代码和这个是一样的,就是换了下方向,需要自己定义下。

五、定义图片的点击事件

1、定义interface来监听事件

在自定义控件中自定义一个interface来监听事件就可以了。

public interface ionclicklistener {
  void onitemclick(view view, int position);
 }

2、在ontouch中调用点击事件。

这里需要说明下为什么在ontouch中处理,因为ontouch是触摸事件,在滑动的过程中,用户是触摸了屏幕的,所以根据用户触摸屏幕时点击下的x坐标和点击起来时的x坐标的对比来判断是左滑还是右滑了,这样的话,就会和onclick事件相冲了,所以就想到了一个办法,那就是在范围内的话,就默认为点击事件,范围外就是滑动事件了。

if (0==(math.abs(touchupx - touchdownx))||(math.abs(touchupx - touchdownx))<50) {
    if (listener != null) {
     stopautoplay();
     listener.onitemclick(view, pictureindex);
     handler.sendemptymessagedelayed(start_auto_play,autoplayduration);
    }
}

六、效果图

说到了这里,应该有所思路了吧,现在就来看下效果吧。

Android仿京东淘宝自动无限循环轮播控件思路详解

源代码目前已经开放了,放在github上面,欢迎指导建议。http://www.github.com/lt5505/sliderlayout

以上所述是小编给大家介绍的android仿京东淘宝自动无限循环轮播控件思路详解,希望对大家有所帮助