一行代码引入 ViewPager 无限循环 + 页码显示

简介: (出处:http://www.cnblogs.com/linguanh)   前序:   网上的这类 ViewPager 很多,但是很多都不够好,体现在 bug多、对少页面不支持,例如1~2张图片、功能整合不全(无限+页码)等等,本类由我从零到无完成的,基本已找完 bug,注释丰富,方便大家理解。

(出处:http://www.cnblogs.com/linguanh)

 

前序:

  网上的这类 ViewPager 很多,但是很多都不够好,体现在 bug多、对少页面不支持,例如1~2张图片、功能整合不全(无限+页码)等等,本类由我从零到无完成的,基本已找完 bug,注释丰富,方便大家理解。

 

特点:

  1,代码量少 , 共两个类,约合 310 行代码 (除去注释)

  2,可扩展 , 再加个 handler 即可实现自动轮播

  3,时间复杂度低

  4,耦合度低,只依赖了 imageLoader,可以自己切换

  5,关键点皆给出了详细注释,方便二次开发

 

功能:

  1,右滑无限循环(2^32,或更大),支持页面数>=2, 左滑循环直至原始第一张;

  2,上述效果伴随着正确的页面小点显示,具体效果可自定义

 

使用:

      // 第一个参数是 Activity;第二个是 ViewPager 对象;第三个是 imageLoader 实例,若使用自己的方法加载图片,请修改代码;第四个是图片链接字符串数组  

       new MyViewPager(this,viewpager,imageLoder,imageUrls) 

             .setUnClickLooper(true) // 设置开启第一种效果的无限循环

             .setClickLooper(true)    //  设置开启第二种效果的无限循环

             .init();                         //  实例化全部  

 

效果图:

  第一类效果,布局嵌套时,缩略图形式显示滑动

  

  第二类效果,点击单张图片进入 dialog 风格,大图显示形式

 

 

类简介:

  上述两种效果都能自己选择是否开启无限滑动。

  LoopViewpagerAdapter 类,继承于 PagerAdapter,主要实现功能是无限循环,逻辑处理比较集中于此,通过接口方式加载页 View。
  1 package cn.share.bananacloud.coustomViews.coustomEdittextInput.MyViewPager;
  2 
  3 import android.app.Activity;
  4 import android.support.v4.view.PagerAdapter;
  5 import android.util.Log;
  6 import android.view.LayoutInflater;
  7 import android.view.View;
  8 import android.view.ViewGroup;
  9 
 10 /**
 11  * Created by 林冠宏 on 2016/4/9.
 12  *
 13  * viewPager 无限循环
 14  *
 15  */
 16 
 17 public class LoopViewpagerAdapter extends PagerAdapter{
 18 
 19     private int images;
 20     private String[] imageUrls;
 21     private View[] views;
 22     private boolean isLooper;
 23     private LayoutInflater layoutInflater;
 24     private getItemViewListener getItemViewListener;
 25 
 26     public LoopViewpagerAdapter(
 27             Activity activity,
 28             String[] imageUrls,
 29             boolean isLooper, /** 是否进行无限循环 */
 30             getItemViewListener getItemViewListener)
 31     {
 32         this.isLooper = isLooper;
 33         this.images = imageUrls.length;
 34         this.layoutInflater = activity.getLayoutInflater();
 35         this.imageUrls = imageUrls;
 36         views = new View[images];
 37         this.getItemViewListener = getItemViewListener;
 38     }
 39 
 40     @Override
 41     public int getCount() {
 42         if(isLooper){
 43             if(images<3){ /** 1~2 张图片的情况 强制不开启循环 */
 44                 return images;
 45             }else {
 46                 return 65535; /** 设置足够大 2^32 */
 47             }
 48         }else{
 49             return images;
 50         }
 51     }
 52 
 53     /** 调用顺序 destroyItem -> instantiateItem */
 54 
 55     @Override
 56     public void destroyItem(ViewGroup container, int position, Object object) {
 57         Log.d("zzzzz","destroy "+position);
 58         container.removeView((View) object); /** 和 instantiateItem 相照应,这个是移除,不用担心内存会累加 */
 59     }
 60 
 61     @Override
 62     public Object instantiateItem(ViewGroup container,int position) {
 63         Log.d("zzzzz", "position " + position);
 64         if(isLooper && images==3){
 65             /** 3张的特殊处理,在先右滑了一定张数后,再左滑,此时初始化的 距离当前位置 的第前2张和后面一张会重复 (x-2) == (x+1) */
 66             View view = getItemViewListener.getItemView(layoutInflater, container, imageUrls[position%images], position);
 67             container.addView(view);
 68             return view;
 69         }else {
 70             if (position < images) {
 71                 if (views[position] == null) {
 72                     views[position] = getItemViewListener.getItemView(layoutInflater, container, imageUrls[position], position);
 73                 }
 74             } else if (position == images && isLooper) { /** 解决由 setCurrentItem 引发的问题 */
 75                 /** 时间复杂度不高,每经过一次,进入一次 */
 76                 /** 如果看大图vp 从临界最大值点击进来,此时没有之前的 view 赋值,直接 view[max-1] 会造成 空指针 exception,这是会初始化的有 max-2,max,max-1 */
 77                 /*if(images>2){ // 最小情况的判断,因为此时的 container 还没有移除下标 0 的图片,再添加的话会造成不能重复添加的异常
 78                     views[0] = getItemViewListener.getItemView(layoutInflater,container,imageUrls[0],0);
 79                 }else{ // 刚好是 2 张,手动移除下标 0
 80 
 81                 }*/
 82                 /** 如果 共4张图,此时 positon = 3 setCurrentItem() 就会造成加载了 4-2,4,4-1,4 在 view[] 是越界状态,故需要手动赋值 0,2和3 也初始化了,但是 1 没
 83                  *  若一直右滑,到 下标 1 便会抛 Cannot add a null child view to a ViewGroup,所以要 加上 views[images - 3] 也初始化
 84                  * */
 85                 views[0] = getItemViewListener.getItemView(layoutInflater, container, imageUrls[0], 0);
 86                 views[images - 3] = getItemViewListener.getItemView(layoutInflater, container, imageUrls[images - 3], 0);
 87                 container.addView(views[0]);  /** add 0 不会有问题, */
 88                 return views[0];
 89             }
 90         }
 91 
 92         container.addView(views[position%images]);
 93         return views[position%images];
 94     }
 95 
 96     @Override
 97     public boolean isViewFromObject(View view, Object o){
 98         return view.equals(o);
 99     }
100 
101     public interface getItemViewListener{
102         View getItemView(LayoutInflater layoutInflater,ViewGroup container,final String url,final int position);
103     }
104 
105 }
View Code

  

  MyViewPager 类,无父类,内部使用了 LoopViewpagerAdapter ,在无限循环的基础上,附加实现了页码小点的显示。
  1 package cn.share.bananacloud.coustomViews.coustomEdittextInput.MyViewPager;
  2 
  3 import android.app.Activity;
  4 import android.app.AlertDialog;
  5 import android.graphics.Bitmap;
  6 import android.support.v4.view.ViewPager;
  7 import android.util.Log;
  8 import android.view.LayoutInflater;
  9 import android.view.MotionEvent;
 10 import android.view.View;
 11 import android.view.ViewGroup;
 12 import android.view.Window;
 13 import android.widget.ImageView;
 14 import android.widget.LinearLayout;
 15 import android.widget.ProgressBar;
 16 import android.widget.TextView;
 17 
 18 import com.nostra13.universalimageloader.core.ImageLoader;
 19 import com.nostra13.universalimageloader.core.assist.FailReason;
 20 import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
 21 
 22 import cn.share.bananacloud.R;
 23 import cn.share.bananacloud.common.commonDataHelper;
 24 import cn.share.bananacloud.coustomViews.coustomEdittextInput.zoomImageView.PhotoView;
 25 import cn.share.bananacloud.tools.imageLoderHelper;
 26 
 27 /**
 28  * Created by 林冠宏 on 2016/4/9.
 29  *
 30  * viewPager 无限滑动 + 点击看大图,仍可滑动 + 当前张号页码
 31  *
 32  */
 33 
 34 public class MyViewPager {
 35 
 36     private Activity activity;
 37     private String[] imageUrls;
 38     protected ImageLoader imageLoder = null;
 39     private ViewPager viewPager;
 40     private int limitTemp = 0; /** 临界中间值 */
 41     private int picnum;
 42     private boolean unClickLooper = false;
 43     private boolean ClickLooper = false;
 44 
 45     public MyViewPager(
 46             Activity activity,
 47             ViewPager viewPager,
 48             ImageLoader imageLoder,
 49             String[] imageUrls
 50     ){
 51         this.activity = activity;
 52         this.imageUrls = imageUrls;
 53         this.imageLoder = imageLoder;
 54         this.viewPager = viewPager;
 55         picnum = imageUrls.length;
 56     }
 57 
 58     public MyViewPager setUnClickLooper(boolean unClickLooper){
 59         this.unClickLooper = unClickLooper;
 60         return this;
 61     }
 62 
 63     public MyViewPager setClickLooper(boolean ClickLooper){
 64         this.ClickLooper = ClickLooper;
 65         return this;
 66     }
 67 
 68     public void init(){
 69         viewPager.setAdapter
 70                 (
 71                         new LoopViewpagerAdapter
 72                                 (
 73                                         activity,
 74                                         imageUrls,
 75                                         unClickLooper,
 76                                         new LoopViewpagerAdapter.getItemViewListener() {
 77                                             @Override
 78                                             public View getItemView(LayoutInflater layoutInflater, ViewGroup container, final String url, final int position) {
 79                                                 View view = layoutInflater.inflate(R.layout.cy_item_main_image, container, false);
 80                                                 ImageView imageView = (ImageView) view.findViewById(R.id.image);
 81                                                 imageView.setOnClickListener(new View.OnClickListener() {
 82                                                     @Override
 83                                                     public void onClick(View v) {
 84                                                         int temp = position%picnum; /** 记得取余数 position 在无限循环的模式不是 0 ~ picnum */
 85                                                         if(temp==0 && position!=0){
 86                                                             showVPimage(picnum-1);
 87                                                         }else{
 88                                                             showVPimage(temp);
 89                                                         }
 90 
 91                                                     }
 92                                                 });
 93                                                 final ProgressBar spinner = (ProgressBar) view.findViewById(R.id.loading);
 94 
 95                                                 imageLoder.displayImage(url, imageView,
 96                                                         imageLoderHelper.getLoderOption(commonDataHelper.phoneWidth, R.drawable.hot_live_default_image, 0), new SimpleImageLoadingListener() {
 97                                                             @Override
 98                                                             public void onLoadingStarted(String imageUri, View view) {
 99                                                                 spinner.setVisibility(View.VISIBLE);
100                                                                 Log.d("zzzzz", "onLoadingStarted");
101                                                             }
102 
103                                                             @Override
104                                                             public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
105                                                                 spinner.setVisibility(View.GONE);
106                                                             }
107 
108                                                             @Override
109                                                             public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
110                                                                 Log.d("zzzzz", "onLoadingComplete "+imageUri);
111                                                                 spinner.setVisibility(View.GONE);
112                                                             }
113                                                         });
114                                                 return view;
115                                             }
116                                         }
117                                 )
118                 );
119 
120         viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
121             @Override
122             public void onPageScrolled(int i, float v, int i1) {
123 
124             }
125 
126             @Override
127             public void onPageSelected(int i) { /** 先于 instantiateItem 执行 */
128                 TextView nowCount = (TextView) activity.findViewById(R.id.nowCount);
129                 if((i+1)%picnum==0){
130                     nowCount.setText("" + picnum + " /");
131                 }else {
132                     nowCount.setText("" + (i + 1) % picnum + " /");
133                 }
134             }
135 
136             @Override
137             public void onPageScrollStateChanged(int i) {
138 
139             }
140         });
141     }
142 
143     private void showVPimage(int positon) {
144         final AlertDialog dlg = new AlertDialog.Builder(activity).create();
145 
146         View localView = LayoutInflater.from(activity).inflate(R.layout.viewpager, null);
147 
148         localView.setOnTouchListener(new View.OnTouchListener() {
149             @Override
150             public boolean onTouch(View v, MotionEvent event) {
151                 dlg.dismiss();
152                 return false;
153             }
154         });
155 
156         ViewPager viewPager = (ViewPager) localView.findViewById(R.id.imageContainer);
157         final LinearLayout pointContainer = (LinearLayout) localView.findViewById(R.id.pointContainer);
158         for(int i=0;i<picnum;i++){
159             ImageView imageView = (ImageView) LayoutInflater.from(activity).inflate(R.layout.viewpager_point,pointContainer,false);
160             pointContainer.addView(imageView);
161         }
162         viewPager.setAdapter
163                 (
164                         new LoopViewpagerAdapter
165                                 (
166                                         activity,
167                                         imageUrls,
168                                         ClickLooper,
169                                         new LoopViewpagerAdapter.getItemViewListener() {
170                                             @Override
171                                             public View getItemView(LayoutInflater layoutInflater, ViewGroup container, String url, int position) {
172                                                 View view = layoutInflater.inflate(R.layout.show_big_pic, container, false);
173                                                 PhotoView imageView = (PhotoView) view.findViewById(R.id.bigImage);
174                                                 imageView.setdimissDialog(new PhotoView.dimissDialog() {
175                                                     @Override
176                                                     public void doDimissDialog() {
177                                                         dlg.dismiss();
178                                                     }
179                                                 });
180                                                 try {
181                                                     imageLoder.displayImage
182                                                             (
183                                                                     url,
184                                                                     imageView,
185                                                                     imageLoderHelper.getLoderOption(commonDataHelper.phoneWidth+50, R.drawable.hot_live_default_image,0)
186                                                             );
187                                                 } catch (Exception ignored){}
188                                                 return view;
189                                             }
190                                         }
191                                 )
192                 );
193         viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
194             @Override
195             public void onPageScrolled(int i, float v, int i1) {
196 
197             }
198 
199             @Override
200             public void onPageSelected(int i) { /** 先于 instantiateItem 执行 */
201                 Log.d("onPageSelected","onPageSelected ->"+i);
202                 /** 为了减少 CPU 和 内存的 绘图消耗,这里不采用 for 等循环的方式改 点背景,改用条件语句 */
203                 if(ClickLooper){
204                     Log.d("onPageSelected","i is ->"+i +" limitTemp is "+limitTemp);
205                     /** 循环情况临界点的颜色恢复 */
206                     if((i % picnum)==(picnum-1) && limitTemp == 0){  /** 左滑 */
207                         ((ImageView) pointContainer.getChildAt(0)).setImageResource(R.drawable.white_point_xml);
208                     }else {
209                         if (i >= picnum && i % picnum == 0) { /** 右滑 */
210                             ((ImageView) pointContainer.getChildAt(picnum - 1)).setImageResource(R.drawable.white_point_xml);
211                         }
212                     }
213                 }
214                 i = i % picnum;
215                 ((ImageView) pointContainer.getChildAt(i)).setImageResource(R.drawable.color_point);
216                 if (i != 0 && i != picnum - 1) { /** 非临界值,两边都要修改 */
217                     ((ImageView) pointContainer.getChildAt(i>limitTemp ? i-1:i+1)).setImageResource(R.drawable.white_point_xml);
218                 }else {
219                     ((ImageView) pointContainer.getChildAt(i==picnum-1 ? i-1:i+1)).setImageResource(R.drawable.white_point_xml);
220                 }
221                 limitTemp = i;
222             }
223 
224             @Override
225             public void onPageScrollStateChanged(int i) {
226 
227             }
228         });
229         viewPager.setCurrentItem(positon);
230         ((ImageView)pointContainer.getChildAt(positon)).setImageResource(R.drawable.color_point);
231 
232 
233         Window localWindow = dlg.getWindow();
234         localWindow.getAttributes();
235         dlg.show();
236         localWindow.setContentView(localView);
237         localWindow.setGravity(17);
238         localWindow.setLayout(-1, -1);
239     }
240 
241 }
View Code

 

Demo项目 github 链接:

  https://github.com/af913337456/lghLoopViewPager?files=1

 
 

如果您认为这篇文章还不错或者有所收获,您可以通过扫描一下下面的支付宝二维码 打赏我一杯咖啡【物质支持】,也可以点击右下角的【推荐】按钮【精神支持】,因为这两种支持都是我继续写作,分享的最大动力


img_12e3f54d4d0f70f0eb14f20548e3d781.png
目录
相关文章
|
Android开发
两种方法,教你解决 ViewPager 嵌套 ViewPager滑动冲突(一)
两种方法,教你解决 ViewPager 嵌套 ViewPager滑动冲突
|
Android开发 容器
Android viewpage 设定上一页下一页按钮
Viewpager,视图翻页工具,提供了多页面切换的效果。Android 3.0后引入的一个UI控件,位于v4包中。低版本使用需要导入v4包,但是现在我们开发的APP一般不再兼容3.0及以下的系统版本,另外现在大多数使用Android studio进行开发,默认导入v7包,v7包含了v4,所以不用导包,越来越方便了。
315 1
Android viewpage 设定上一页下一页按钮
|
XML 数据格式 容器
翻页类视图 ViewPager
翻页类视图 ViewPager一、ViewPage简单介绍
翻页类视图 ViewPager
|
Android开发
ViewPager源码分析(2):滑动及冲突处理
我的简书同步发布:ViewPager源码分析(2):滑动及冲突处理 转载请注明出处:【huachao1001的专栏:http://blog.csdn.net/huachao1001】 上一篇介绍了ViewPager的onMeasure和onLayout两个方法,这是自定义View最基本的两个函数。但是我们的ViewPager有个需求就是滑动,接下来我们一起去学习ViewPager在滑动方面做了哪些工作,以及ViewPager如何处理与子View之间的滑动冲突。由于ViewPager的子View有Decor View还有普通的子View,而本篇文章讲的主要是普通子View,因此,不再去刻意区
ViewPager源码分析(2):滑动及冲突处理
|
容器
使用Fragmentation,start跳转到嵌套viewpager页面出现返回键重写失效原因。
最近在写项目时,采用的是单Activity+多Fragment的架构,用的Fragmentation的库。我的主页面是一个BootomFragment的抽象类(当然它还有一个管理类),其又继承自最大的LatteDelegate,LatteDelegate又继承自Fragment并实现Fragmentation库的接口,当然,当然这只是其中一部分,所以简略的讲了一下,大概知道层次就行。
104 0
使用Fragmentation,start跳转到嵌套viewpager页面出现返回键重写失效原因。
|
缓存
ViewPager懒加载的实现,理解setUserVisibleHint,而不只是会用就好
Viewpager默认会缓存临近操作的两个页面,也就是至少会缓存一个页面。
206 0
ViewPager懒加载的实现,理解setUserVisibleHint,而不只是会用就好
ViewPager2实现内部Item的动态滚动
最近接到了一个需求,大概类似如下图所示的一个样式(省略了部分细节,不影响大概)。
341 0
BottomNavigationView使用,配合ViewPager、修改图标大小、去掉文字等
BottomNavigationView使用,配合ViewPager、修改图标大小、去掉文字等
674 0
BottomNavigationView使用,配合ViewPager、修改图标大小、去掉文字等
fragment嵌套viewpager不显示
fragment嵌套viewpager不显示
191 0
ViewPager(通过反射修改viewpager切换速度)
(创建于2016/11/17) import java.lang.reflect.Field; import android.content.
1122 0