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

在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="0" />
 5             <enum name="rect" value="1" />
 6         </attr>
 7         <attr name="sl_indicator_position" format="enum">
 8             <enum name="centerBottom" value="0" />
 9             <enum name="rightBottom" value="1" />
10             <enum name="leftBottom" value="2" />
11             <enum name="centerTop" value="3" />
12             <enum name="rightTop" value="4" />
13             <enum name="leftTop" value="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);
 2         if (array != null) {
 3             isAutoPlay = array.getBoolean(R.styleable.SliderLayout_sl_is_auto_play, isAutoPlay);
 4             //get the shape of indicator
 5             int intShape = array.getInt(R.styleable.SliderLayout_sl_indicator_shape, indicatorShape.ordinal());
 6             for (IndicatorShape shape : IndicatorShape.values()) {
 7                 if (shape.ordinal() == intShape) {
 8                     indicatorShape = shape;
 9                     break;
10                 }
11             }
12             //get the position of indicator
13             int intPosition = array.getInt(R.styleable.SliderLayout_sl_indicator_position, IndicatorPosition.centerBottom.ordinal());
14             for (IndicatorPosition position : IndicatorPosition.values()) {
15                 if (position.ordinal() == intPosition) {
16                     indicatorPosition = position;
17                     break;
18                 }
19             }
20             unSelectedIndicatorColor = array.getColor(R.styleable.SliderLayout_sl_unselected_indicator_color, unSelectedIndicatorColor);
21             selectedIndicatorColor = array.getColor(R.styleable.SliderLayout_sl_selected_indicator_color, selectedIndicatorColor);
22             unSelectedIndicatorHeight = array.getDimension(R.styleable.SliderLayout_sl_unselected_indicator_height, unSelectedIndicatorHeight);
23             unSelectedIndicatorWidth = array.getDimension(R.styleable.SliderLayout_sl_unselected_indicator_width, unSelectedIndicatorWidth);
24             selectedIndicatorHeight = array.getDimension(R.styleable.SliderLayout_sl_selected_indicator_height, selectedIndicatorHeight);
25             selectedIndicatorWidth = array.getDimension(R.styleable.SliderLayout_sl_selected_indicator_width, selectedIndicatorWidth);
26             indicatorSpace = array.getDimension(R.styleable.SliderLayout_sl_indicator_space, indicatorSpace);
27             indicatorMargin = array.getDimension(R.styleable.SliderLayout_sl_indicator_margin, indicatorMargin);
28             autoPlayDuration = array.getInt(R.styleable.SliderLayout_sl_auto_play_duration, autoPlayDuration);
29             defaultImage = array.getResourceId(R.styleable.SliderLayout_sl_default_image, defaultImage);
30             errorImage = array.getResourceId(R.styleable.SliderLayout_sl_error_image, errorImage);
31         }

2、初始化控件

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

 1 switcherImage = new ImageSwitcher(context);
 2         switcherImage.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
 3
 4 for (int i = 0; i < itemCount; i++) {
 5             ImageView indicator = new ImageView(context);
 6             indicator.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
 7             indicator.setPadding((int) (indicatorSpace), (int) (indicatorSpace), (int) (indicatorSpace), (int) (indicatorSpace));
 8             indicator.setImageDrawable(unSelectedDrawable);
 9             indicatorContainer.addView(indicator);
10             final int finalI = i;
11             indicator.setOnClickListener(new OnClickListener() {
12                 @Override
13                 public void onClick(View view) {
14                     stopAutoPlay();
15                     switchIndicator(finalI);
16                     pictureIndex = finalI;
17                     handler.sendEmptyMessageDelayed(START_AUTO_PLAY,autoPlayDuration);
18                 }
19             });
20         }

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

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

函数代码如下。

1 private void switchIndicator(int index) {
2         for (int i = 0; i < indicatorContainer.getChildCount(); i++) {
3             ((ImageView) indicatorContainer.getChildAt(i)).setImageDrawable(i == index ? selectedDrawable : unSelectedDrawable);
4         }
5         loadImage(index);
6     }

调用选中第一张图。

1 switchIndicator(0);

三、图片的加载

1、网路图片的加载

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

 1 private void loadNetImage(int pictureIndex) {
 2         if (list != null && list.size() != 0) {
 3             Picasso.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
 4         public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
 5             dismissDialog();
 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
12         public void onBitmapFailed(Drawable errorDrawable) {
13             dismissDialog();
14             ((ImageView) switcherImage.getCurrentView()).setImageDrawable(errorDrawable);
15         }
16
17         @Override
18         public void onPrepareLoad(Drawable placeHolderDrawable) {
19             showDialog();
20         }
21     };

2、加载资源图片

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

1 private void loadFileImage(int pictureIndex) {
2         if (list != null && list.size() != 0) {
3             switcherImage.setImageResource((Integer) list.get(pictureIndex));
4         }
5     }

四、设置图片切换的动画

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

 1 private void SliderLeftToRight() {
 2         // get current index
 3         pictureIndex = pictureIndex == 0 ? itemCount - 1
 4                 : pictureIndex - 1;
 5         // set Animation
 6         switcherImage.setInAnimation(AnimationUtils.loadAnimation(context,
 7                 android.R.anim.slide_in_left));
 8         switcherImage.setOutAnimation(AnimationUtils.loadAnimation(context,
 9                 android.R.anim.slide_out_right));
10         switchIndicator(pictureIndex);
11     }

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

五、定义图片的点击事件

1、定义interface来监听事件

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

1 public interface IOnClickListener {
2
3         void 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
3                 if (listener != null) {
4
5                     stopAutoPlay();
6                     listener.onItemClick(view, pictureIndex);
7                     handler.sendEmptyMessageDelayed(START_AUTO_PLAY,autoPlayDuration);
8                 }
9 }

六、效果图

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

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

时间: 2024-08-24 08:50:09

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

浅谈android中仅仅使用一个TextView实现高仿京东,淘宝各种倒计时

今天给大家带来的是仅仅使用一个TextView实现一个高仿京东.淘宝.唯品会等各种电商APP的活动倒计时.最近公司一直加班也没来得及时间去整理,今天难得休息想把这个分享给大家,只求共同学习,以及自己后续的复习.为什么会想到使用一个TextView来实现呢?因为最近公司在做一些优化的工作,其中就有一个倒计时样式,原来开发的这个控件的同事使用了多个TextView拼接在一起的,实现的代码冗余比较大,故此项目经理就说:小宏这个就交给你来优化了,并且还要保证有一定的扩展性,当时就懵逼了.不知道从何处开始

浅谈android中只使用一个TextView实现高仿京东,淘宝各种倒计时

今天给大家带来的是只使用一个TextView实现一个高仿京东.淘宝.唯品会等各种电商APP的活动倒计时.近期公司一直加班也没来得及时间去整理,今天难得歇息想把这个分享给大家.只求共同学习,以及自己兴许的复习. 为什么会想到使用一个TextView来实现呢?由于近期公司在做一些优化的工作,当中就有一个倒计时样式,原来开发的这个控件的同事使用了多个TextView拼接在一起的.实现的代码冗余比較大.故此项目经理就说:小宏这个就交给你来优化了.而且还要保证有一定的扩展性,当时就懵逼了.不知道从何处開始

使用递归制作仿京东淘宝的商品分类导航栏

前些天,培训ASP.NET的老师布置了作业,制作商城的一些重要功能, 昨天做了一下其中比较难的商品分类导航类,使用了递归的方法. ps:使用的是WebForm,希望看到MVC的同学请忽略. 最终效果图: 下面记录一下: 首先是数据库部分,使用的是SQL,在一张叫做Category的表中,设置了以下字段: [Id] 分类的Id,int,自增长[Name] 分类的名称,nvarchar(50)[ParentId] 父类的Id,int[Link] 链接地址,varchar(max),用于打开链接,也可

小鲜肉初学JS做得仿京东淘宝竖排二级导航

<!DOCTYPE html><html><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><title></title><meta name="description" content=""

仿京东淘宝商品详情页属性选择js效果

在网上找了好久发现都不符合要求就自己摸索写了一个,用到了linq.js这个linq to js 扩展,不然用纯JS遍历json查询要死人啊 效果图: 代码直接拷贝就可以运行: <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <script src="http://libs.baidu.com/jquery/

Android 超简单自动无限轮播图LoopView

只需要你传入数据就可以了 效果图 demo地址 https://github.com/wanghao200906/Android-LoopView 效果实现 1.添加依赖库 2.添加到xml < com.kevin.loopview.AdLoopView android:id="@+id/main_act_adloopview" android:layout_width="match_parent" android:layout_height="54

JQuery仿最新淘宝网首页带箭头幻灯片,JQuery轮播图

JQuery代码 <script type="text/javascript"> $(function() { var $banner = $('.banner'); var $banner_ul = $('.banner-img'); var $btn = $('.banner-btn'); var $btn_a = $btn.find('a') var v_width = $banner.width(); var page = 1; var timer = null;

Android自动滚动 轮播循环的ViewPager

主要介绍如何实现ViewPager自动播放,循环滚动的效果及使用.顺便解决ViewPager嵌套(ViewPager inside ViewPager)影响触摸滑动及ViewPager滑动速度设置问题. 项目已开源Android Auto Scroll [email protected],欢迎star和fork. 示例APK可从这些地址下载:Google Play,  360手机助手,  百度手机助手,  小米应用商店,  豌豆荚 示例代码地址见AutoScrollViewPagerDemo,效

仿网易云音乐 专辑图片折叠轮播

仿网易云音乐 专辑图片折叠轮播 先不多说现上一张效果图 首先简述一下实现原理 1.首先让我们的imageview**动起来** 其实是不断的.invalidate();函数 让他不断的调用ondarw函数 (显然我们不必要不断的调用ondarw函数 只有在我们让他动的时候调用即可 所以我们要声明一个变量记录change记录是否产生动画) 2.实现我们的可折叠效果 Matrix的setPolyToPoly方法的使用 可参考(http://blog.csdn.net/lmj623565791/art