Android之仿京东淘宝的自动无限轮播控件

少年击剑更吹箫,剑气箫心一例消。这篇文章主要讲述Android之仿京东淘宝的自动无限轮播控件相关的知识,希望能为你提供帮助。
在App的开发中,很多的时候都需要实现类似京东淘宝一样的自动无限轮播的广告栏,所以就自己写了一个,下面是我自定义控件的思路和过程。在App的开发中,很多的时候都需要实现类似京东淘宝一样的自动无限轮播的广告栏,所以就自己写了一个,下面是我自定义控件的实现思路和过程。
一、自定义控件属性
新建自定义控件SliderLayout继承于RelativeLayout,首先要考虑的就是自定义的控件需要扩展那些属性,把这些属性列出来。在这里是要实现类似于京东淘宝的无限轮播广告栏,那么首先想到的就是轮播的时长、轮播指示器的样式等等。我在这里列举了一些并且结合到了代码中。
1、扩展属性
(1)是否开启自动轮播的功能。
(2)指示器的图形样式,一般为圆形和方形两种。
(3)指示器的位置,一般为底部或者顶部。
(4)指示器被选中和不被选中时的样式:颜色、高度、宽度、间隔等。
(5)轮播的时长。
(6)加载的如果是网络图片的话,需要默认图片和错误图片等。
 
2、在attrs.xml文件中添加这些扩展的属性。

1 < declare-styleable name="SliderLayout"> 2< attr name="sl_is_auto_play" format="boolean"/> 3< attr name="sl_indicator_shape" format="enum"> 4< enum name="oval" value="https://www.songbingjia.com/android/0" /> 5< enum name="rect" value="https://www.songbingjia.com/android/1" /> 6< /attr> 7< attr name="sl_indicator_position" format="enum"> 8< enum name="centerBottom" value="https://www.songbingjia.com/android/0" /> 9< enum name="rightBottom" value="https://www.songbingjia.com/android/1" /> 10< enum name="leftBottom" value="https://www.songbingjia.com/android/2" /> 11< enum name="centerTop" value="https://www.songbingjia.com/android/3" /> 12< enum name="rightTop" value="https://www.songbingjia.com/android/4" /> 13< enum name="leftTop" value="https://www.songbingjia.com/android/5" /> 14< /attr> 15< attr name="sl_selected_indicator_color" format="color|reference" /> 16< attr name="sl_unselected_indicator_color" format="color|reference" /> 17 18< attr name="sl_selected_indicator_height" format="dimension|reference" /> 19< attr name="sl_selected_indicator_width" format="dimension|reference" /> 20 21< attr name="sl_unselected_indicator_height" format="dimension|reference" /> 22< attr name="sl_unselected_indicator_width" format="dimension|reference" /> 23 24< attr name="sl_indicator_space" format="dimension|reference" /> 25< attr name="sl_indicator_margin" format="dimension|reference" /> 26< attr name="sl_auto_play_duration" format="integer|reference" /> 27< attr name="sl_default_image" format="reference"/> 28< attr name="sl_error_image" format="reference"/> 29< /declare-styleable>

二、自定义轮播控件的初始化
1、获取到扩展属性的值
在自定义SliderLayout中获取到扩展的样式,然后根据样式获取相应的属性值,最好是要先设置好默认值。
1 TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.SliderLayout, defStyleAttr, 0); 2if (array != null) { 3isAutoPlay = array.getBoolean(R.styleable.SliderLayout_sl_is_auto_play, isAutoPlay); 4//get the shape of indicator 5int intShape = array.getInt(R.styleable.SliderLayout_sl_indicator_shape, indicatorShape.ordinal()); 6for (IndicatorShape shape : IndicatorShape.values()) { 7if (shape.ordinal() == intShape) { 8indicatorShape = shape; 9break; 10} 11} 12//get the position of indicator 13int intPosition = array.getInt(R.styleable.SliderLayout_sl_indicator_position, IndicatorPosition.centerBottom.ordinal()); 14for (IndicatorPosition position : IndicatorPosition.values()) { 15if (position.ordinal() == intPosition) { 16indicatorPosition = position; 17break; 18} 19} 20unSelectedIndicatorColor = array.getColor(R.styleable.SliderLayout_sl_unselected_indicator_color, unSelectedIndicatorColor); 21selectedIndicatorColor = array.getColor(R.styleable.SliderLayout_sl_selected_indicator_color, selectedIndicatorColor); 22unSelectedIndicatorHeight = array.getDimension(R.styleable.SliderLayout_sl_unselected_indicator_height, unSelectedIndicatorHeight); 23unSelectedIndicatorWidth = array.getDimension(R.styleable.SliderLayout_sl_unselected_indicator_width, unSelectedIndicatorWidth); 24selectedIndicatorHeight = array.getDimension(R.styleable.SliderLayout_sl_selected_indicator_height, selectedIndicatorHeight); 25selectedIndicatorWidth = array.getDimension(R.styleable.SliderLayout_sl_selected_indicator_width, selectedIndicatorWidth); 26indicatorSpace = array.getDimension(R.styleable.SliderLayout_sl_indicator_space, indicatorSpace); 27indicatorMargin = array.getDimension(R.styleable.SliderLayout_sl_indicator_margin, indicatorMargin); 28autoPlayDuration = array.getInt(R.styleable.SliderLayout_sl_auto_play_duration, autoPlayDuration); 29defaultImage = array.getResourceId(R.styleable.SliderLayout_sl_default_image, defaultImage); 30errorImage = array.getResourceId(R.styleable.SliderLayout_sl_error_image, errorImage); 31}

2、初始化控件
根据这里所需要实现的功能,首先需要一个图像切换器ImageSwticher,还要指示器,这里就用ImageView了。
1 switcherImage = new ImageSwitcher(context); 2switcherImage.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); 3 4 for (int i = 0; i < itemCount; i++) { 5ImageView indicator = new ImageView(context); 6indicator.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); 7indicator.setPadding((int) (indicatorSpace), (int) (indicatorSpace), (int) (indicatorSpace), (int) (indicatorSpace)); 8indicator.setImageDrawable(unSelectedDrawable); 9indicatorContainer.addView(indicator); 10final int finalI = i; 11indicator.setOnClickListener(new OnClickListener() { 12@Override 13public void onClick(View view) { 14stopAutoPlay(); 15switchIndicator(finalI); 16pictureIndex = finalI; 17handler.sendEmptyMessageDelayed(START_AUTO_PLAY,autoPlayDuration); 18} 19}); 20}

3、初始化选中第一张图片
专门写一个针对指示器切换的函数,然后在初始化的时候直接调用,选中第一个指示器,就是选中第一张图片了。
函数代码如下。
1 private void switchIndicator(int index) { 2for (int i = 0; i < indicatorContainer.getChildCount(); i++) { 3((ImageView) indicatorContainer.getChildAt(i)).setImageDrawable(i == index ? selectedDrawable : unSelectedDrawable); 4} 5loadImage(index); 6}

调用选中第一张图。
    1 switchIndicator(0);  
三、图片的加载
1、网路图片的加载
在这里使用Picasso框架来加载图片,根据url来加载显示图片,同时也要显示图片的加载进度,这里就需要一个Dialog提示框了,Dialog的样式最好是可以自定义的。
1 private void loadNetImage(int pictureIndex) { 2if (list != null & & list.size() != 0) { 3Picasso.with(context) 4.load((String) list.get(pictureIndex)) 5.placeholder(defaultImage) 6.error(errorImage) 7.tag(context) 8.into(mTarget); 9} 10}

下面是图片的加载提示过程。
1 private Target mTarget = new Target() { 2 3@Override 4public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) { 5dismissDialog(); 6((ImageView) switcherImage.getCurrentView()).setScaleType(ImageView.ScaleType.CENTER_CROP); 7((ImageView) switcherImage.getCurrentView()).setLayoutParams(new ImageSwitcher.LayoutParams(ImageSwitcher.LayoutParams.MATCH_PARENT, ImageSwitcher.LayoutParams.MATCH_PARENT)); 8((ImageView) switcherImage.getCurrentView()).setImageBitmap(bitmap); 9} 10 11@Override 12public void onBitmapFailed(Drawable errorDrawable) { 13dismissDialog(); 14((ImageView) switcherImage.getCurrentView()).setImageDrawable(errorDrawable); 15} 16 17@Override 18public void onPrepareLoad(Drawable placeHolderDrawable) { 19showDialog(); 20} 21};

2、加载资源图片
只能加载网络图片是不够的呢,还需要可以加载资源图片,加载资源图片的办法就更加简单了。
1 private void loadFileImage(int pictureIndex) { 2if (list != null & & list.size() != 0) { 3switcherImage.setImageResource((Integer) list.get(pictureIndex)); 4} 5}

四、设置图片切换的动画
设置图片从左往右以及从右往左的动画效果,并且当滑动到该图片时,指示器也要一起变化,这里就简单说下从左往右的动画了。
 
1 private void SliderLeftToRight() { 2// get current index 3pictureIndex = pictureIndex == 0 ? itemCount - 1 4: pictureIndex - 1; 5// set Animation 6switcherImage.setInAnimation(AnimationUtils.loadAnimation(context, 7android.R.anim.slide_in_left)); 8switcherImage.setOutAnimation(AnimationUtils.loadAnimation(context, 9android.R.anim.slide_out_right)); 10switchIndicator(pictureIndex); 11}

 
从右往左滑动时的代码和这个是一样的,就是换了下方向,需要自己定义下。
五、定义图片的点击事件
1、定义interface来监听事件
在自定义控件中自定义一个interface来监听事件就可以了。
 
1 public interface IOnClickListener { 2 3void onItemClick(View view, int position); 4 5 }

2、在onTouch中调用点击事件。
这里需要说明下为什么在onTouch中处理,因为onTouch是触摸事件,在滑动的过程中,用户是触摸了屏幕的,所以根据用户触摸屏幕时点击下的X坐标和点击起来时的X坐标的对比来判断是左滑还是右滑了,这样的话,就会和onClick事件相冲了,所以就想到了一个办法,那就是在范围内的话,就默认为点击事件,范围外就是滑动事件了。
1 if (0==(Math.abs(touchUpX - touchDownX))||(Math.abs(touchUpX - touchDownX))< 50) { 2 3if (listener != null) { 4 5stopAutoPlay(); 6listener.onItemClick(view, pictureIndex); 7handler.sendEmptyMessageDelayed(START_AUTO_PLAY,autoPlayDuration); 8} 9 }

六、效果图
说到了这里,应该有所思路了吧,现在就来看下效果吧。
Android之仿京东淘宝的自动无限轮播控件

文章图片

 
源代码目前已经开放了,放在Github上面,欢迎指导建议。http://www.github.com/LT5505/SliderLayout
【Android之仿京东淘宝的自动无限轮播控件】 

    推荐阅读