无限循环的Viewpager

网络上有很多无线循环的Viewpager,但是学习嘛,就自己写了一个无线循环的ViewPager。

思路一

网上有一种是真正意义的无限循环,比如View0,View1,View2,View3, 4个View,

在View0左侧加一个View3,View3右侧加一个View0,

就成了View3-2, View0,View1,View2,View3, View0-2,

View3向右滑动,显示的是View0-2,viewPager.setCurrentItem(position,fasle)这个方法跳到View0,

同理View0左滑,显示的是View3-2,同样跳到View3,

这个方法的缺点就是,View0到View3滑动时流畅的,但是View3到View0,是瞬间变化的,不好看。

思路二

Adapter,getCount()设置为   Integer.MAX_VALUE  ,这是一个非常非常大的数,

然后我们一进去就取中间值,无论左滑还是右滑,都能不停的循环加载View,

这些view也是重复使用的,因为这个数非常大,

所以你不会那么无聊,一直挂机,挂到他到底吧,所以就能模拟成无线循环,

而且界面的切换也是如丝般顺滑,我比较倾斜这个算法。 


切换动画是出自鸿洋大神的

出自:http://blog.csdn.net/lmj623565791/article/details/40411921





小圆圈样式
1
2
3
4
5
<?xml version= "1.0"  encoding= "utf-8" ?>
<selector xmlns:android= "http://schemas.android.com/apk/res/android" >
     <item android:drawable= "@drawable/advertisement_circle_1"  android:state_checked= "true" />
     <item android:drawable= "@drawable/advertisement_circle_2"  android:state_checked= "false" />
</selector>
1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version= "1.0"  encoding= "utf-8" ?>
<shape
     android:shape= "oval"
     xmlns:android= "http://schemas.android.com/apk/res/android" >
 
     <solid
         android:color= "#FFFFFF" />
 
     <size
         android:width= "15dp"
         android:height= "15dp" />
 
</shape>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version= "1.0"  encoding= "utf-8" ?>
<shape
     android:shape= "oval"
     xmlns:android= "http://schemas.android.com/apk/res/android" >
 
     <solid
         android:color= "#22FFFFFF" />
 
     <stroke
         android:width= "1dp"
         android:color= "#FFFFFF" />
 
     <size
         android:width= "15dp"
         android:height= "15dp" />
</shape>



Viewpager动画
DepthPageTransformer
这个是出于鸿洋大神的:http://blog.csdn.net/lmj623565791/article/details/40411921
  
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public  class  DepthPageTransformer  implements  ViewPager.PageTransformer
{
     private  static  final  float  MIN_SCALE =  0 .75f;
 
     public  void  transformPage(View view,  float  position)
     {
         int  pageWidth = view.getWidth();
 
         if  (position < - 1 )
         // [-Infinity,-1)
             // This page is way off-screen to the left.
             view.setAlpha( 0 );
 
         else  if  (position <=  0 )
         // [-1,0]
             // Use the default slide transition when moving to the left page
             view.setAlpha( 1 );
             view.setTranslationX( 0 );
             view.setScaleX( 1 );
             view.setScaleY( 1 );
 
         else  if  (position <=  1 )
         // (0,1]
             // Fade the page out.
             view.setAlpha( 1  - position);
 
             // Counteract the default slide transition
             view.setTranslationX(pageWidth * -position);
 
             // Scale the page down (between MIN_SCALE and 1)
             float  scaleFactor = MIN_SCALE
                     + ( 1  - MIN_SCALE) * ( 1  - Math.abs(position));
             view.setScaleX(scaleFactor);
             view.setScaleY(scaleFactor);
 
         else
         // (1,+Infinity]
             // This page is way off-screen to the right.
             view.setAlpha( 0 );
         }
     }
}


LoopViewAdapter,这样写,就一定要用这个Adapter
1
2
3
4
5
6
7
8


/**
  * 要用LoopView一定要使用这个Adapter
  */
public  abstract  class  MyLoopViewAdapter  extends  PagerAdapter
{
     /**
      * 返回真实的view数
      */
     public  abstract  int  getRealCount();
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87


 
public  class  LoopViewAdapter  extends  MyLoopViewAdapter
{
     private  ArrayList<View> views =  new  ArrayList<>();
 
     public  LoopViewAdapter()
     {
     }
 
     public  LoopViewAdapter(ArrayList<View> views)
     {
         this .views = views;
     }
 
     /**
      * 在下标position处添加View
      */
     public  void  insertView(View view,  int  position)
     {
         if  (view !=  null )
         {
             this .views.add(position, view);
             notifyDataSetChanged();
         }
     }
 
     /**
      * 在尾部添加view
      */
     public  void  insertView(View view)
     {
         if  (view !=  null )
         {
             this .views.add(view);
             notifyDataSetChanged();
         }
     }
 
     /**
      * 获取view
      */
     public  View getView( int  position)
     {
         return  this .views.get(position);
     }
 
     @Override
     public  int  getCount()
     {
        //设置为一个很大很大的数
         return  Integer.MAX_VALUE;
     }
 
     @Override
     public  int  getRealCount()
     {
         return  views.size();
     }
 
     @Override
     public  Object instantiateItem( final  ViewGroup container,  int  position)
     {
         final  View view = views.get(position % (views.size()));
 
         //在主线程添加
         container.post( new  Runnable()
         {
             @Override
             public  void  run()
             {
                 container.removeView(view);
                 container.addView(view);
             }
         });
 
         return  view;
     }
 
     @Override
     public  void  destroyItem(ViewGroup container,  int  position, Object object)
     {
     }
 
     @Override
     public  boolean  isViewFromObject(View view, Object object)
     {
         return  view == object;
     }
}


LoopViewPager,默认2000毫秒切换间隔,默认自动循环
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220



 
/**
  * Created by solexit04 on 2016/8/17.
  * 自动轮播Viewpager
  */
public  class  LoopViewPager  extends  RelativeLayout  implements  ViewPager.OnPageChangeListener
{
     //底部小圆圈的样式
     private  int  dotRes = - 1 ;
     //图片轮转周期
     private  int  period =  2000 ;
 
     private  static  final  int  ADVERTISEMENT =  1 ;
     private  ViewPager viewPager;
     private  RadioGroup radioGroup;
     private  LoopViewAdapter loopViewAdapter;
 
     public  LoopViewPager(Context context)
     {
         this (context,  null );
     }
 
     public  LoopViewPager(Context context, AttributeSet attrs)
     {
         this (context, attrs,  0 );
     }
 
     public  LoopViewPager(Context context, AttributeSet attrs,  int  defStyleAttr)
     {
         super (context, attrs, defStyleAttr);
         init();
     }
 
     private  Handler handler =  new  Handler( new  Handler.Callback()
     {
         @Override
         public  boolean  handleMessage(Message msg)
         {
             switch  (msg.what)
             {
                 case  ADVERTISEMENT:
                     viewPager.setCurrentItem(viewPager.getCurrentItem() +  1 );
                     handler.sendEmptyMessageDelayed(ADVERTISEMENT, period);
                     break ;
                 default :
                     break ;
             }
             return  false ;
         }
     });
 
     /**
      * 初始化控件
      */
     private  void  init()
     {
         viewPager =  new  ViewPager(getContext());
         viewPager.addOnPageChangeListener( this );
 
         radioGroup =  new  RadioGroup(getContext());
         //设置RadioGroup为水平排列
         radioGroup.setOrientation(RadioGroup.HORIZONTAL);
 
         //让viewpager填充满怎个布局
         RelativeLayout.LayoutParams params =  new  LayoutParams(LayoutParams.MATCH_PARENT
                 , LayoutParams.MATCH_PARENT);
         viewPager.setLayoutParams(params);
         addView(viewPager);
 
         //设置radioGroup包裹内容
         params =  new  LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
         //设置为水平居中
         params.addRule(CENTER_HORIZONTAL);
         //设置为父布局的底部
         params.addRule(ALIGN_PARENT_BOTTOM);
         radioGroup.setLayoutParams(params);
         addView(radioGroup);
     }
 
     /**
      * 设置小圆点的样式
      */
     public  void  setDotRes( int  dotRes)
     {
         this .dotRes = dotRes;
         if  (dotRes ==  0 )
         {
             return ;
         }
         for  ( int  i =  0 ; i < radioGroup.getChildCount(); i++)
         {
             radioGroup.getChildAt(i).setBackgroundResource(dotRes);
         }
     }
 
     /**
      * 设置底部小圆点RadioGroup是否可见
      */
     public  void  setDotVisible( boolean  visible)
     {
         if  (visible)
         {
             radioGroup.setVisibility(VISIBLE);
         else
         {
             radioGroup.setVisibility(GONE);
         }
     }
 
     /**
      * 设置轮播间隔
      */
     public  void  setPeriod( int  period)
     {
         this .period = period;
     }
 
     /**
      * 设置是否开始滚动
      */
     public  void  startLoop()
     {
         //先移除,防止重复加载
         stopLoop();
         //发送延时消息
         handler.sendEmptyMessageDelayed(ADVERTISEMENT, period);
     }
 
     /**
      * 停止滚动
      */
     public  void  stopLoop()
     {
         handler.removeMessages(ADVERTISEMENT);
     }
 
     /**
      * 返回当前页码
      */
     public  int  getCurrentItem()
     {
         return  viewPager.getCurrentItem() % loopViewAdapter.getRealCount();
     }
 
     /**
      * 设置适配器
      */
     public  void  setAdapter(LoopViewAdapter adapter)
     {
         if  (adapter ==  null )
         {
             return ;
         }
         this .loopViewAdapter = adapter;
         int  count = adapter.getRealCount();
 
         //根据适配器的图片数量,设置小圆点的数量
         for  ( int  i =  0 ; i < count; i++)
         {
             RadioButton radioButton =  new  RadioButton(getContext());
             //给RadioButton一个空的BitmapDrawable对象,骗过setButtonDrawable的过滤,实际上绘制的时候是没有图片资源
             //将RadioButton的小圆点去掉
             radioButton.setButtonDrawable( new  ColorDrawable());
             //设置不能点击
             radioButton.setEnabled( false );
             //设置小圆点的尺寸
             RadioGroup.LayoutParams params =  new  RadioGroup.LayoutParams( 15 15 );
             //设置小圆点的间距
             params.setMargins( 0 0 10 20 );
             radioButton.setLayoutParams(params);
 
             //设置背景样式
             if  (dotRes != - 1 )
             {
                 radioButton.setBackgroundResource(dotRes);
             else
             {
                 radioButton.setBackgroundResource(R.drawable.advertisement_circle);
             }
             radioGroup.addView(radioButton);
         }
 
         //第一个显示为已选定
         RadioButton radioButton = (RadioButton) radioGroup.getChildAt( 0 );
         radioButton.setChecked( true );
 
         viewPager.setAdapter(loopViewAdapter);
         //设置viewPager切换动画
         viewPager.setPageTransformer( true new  DepthPageTransformer());
         //每次打开都会显示Viewpager第一页
         viewPager.setCurrentItem((loopViewAdapter.getCount() /  2 ) -
                 (loopViewAdapter.getCount() /  2 ) % loopViewAdapter.getRealCount());
        //开始循环
        startLoop();
     }
 
     @Override
     public  void  onPageScrolled( int  position,  float  positionOffset,  int  positionOffsetPixels)
     {
     }
 
     @Override
     public  void  onPageSelected( int  position)
     {
         RadioButton radioButton = (RadioButton) radioGroup
                 .getChildAt(position % loopViewAdapter.getRealCount());
         radioButton.setChecked( true );
     }
 
     @Override
     public  void  onPageScrollStateChanged( int  state)
     {
         switch  (state)
         {
             //手拖住就停止计时
             case  ViewPager.SCROLL_STATE_DRAGGING:
                 stopLoop();
                 break ;
             //松开继续继续计时
             case  ViewPager.SCROLL_STATE_IDLE:
                 startLoop();
                 break ;
             default :
                 break ;
         }
     }
}

使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75



 
public  class  LoopViewPagerActivity  extends  AppCompatActivity
{
     private  LoopViewPager loopViewPager;
     private  LoopViewAdapter loopViewAdapter;
 
     @Override
     protected  void  onCreate(Bundle savedInstanceState)
     {
         super .onCreate(savedInstanceState);
         setContentView(R.layout.activity_view);
 
         initView();
     }
 
     private  void  initView()
     {
         loopViewPager = (LoopViewPager) findViewById(R.id.advertisementViewPager);
         //设置间隔,默认2秒,默认开启循环
         loopViewPager.setPeriod( 3000 );
         initAdapter(getImages());
         loopViewPager.setAdapter(loopViewAdapter);
     }
 
     private  void  initAdapter(ArrayList<String> images)
     {
         final  ArrayList<View> views =  new  ArrayList<>();
         for  ( int  i =  0 ; i <  5 ; i++)
         {
             View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.item,  null );
             final  TextView textView = (TextView) view.findViewById(R.id.item_tv);
             textView.setText( "Mo.nica "  + i);
             ImageView imageView = (ImageView) view.findViewById(R.id.item_image);
             //Glide加载图片
             Glide.with(getApplicationContext())
                     .load(images.get(i))
                     .into(imageView);
 
             textView.setOnClickListener( new  View.OnClickListener()
             {
                 @Override
                 public  void  onClick(View v)
                 {
                     Toast.makeText(LoopViewPagerActivity. this , textView.getText().toString(), Toast.LENGTH_SHORT).show();
                 }
             });
             
             view.setOnClickListener( new  View.OnClickListener()
             {
                 @Override
                 public  void  onClick(View v)
                 {
                     Toast.makeText(LoopViewPagerActivity. this ""  + loopViewPager.getCurrentItem(), Toast.LENGTH_SHORT).show();
                     if  (loopViewPager.getCurrentItem() == views.size() -  1 )
                     {
                         finish();
                     }
                 }
             });
             views.add(view);
         }
         loopViewAdapter =  new  LoopViewAdapter(views);
     }
 
     private  ArrayList<String> getImages()
     {
         ArrayList<String> images =  new  ArrayList<>();
         images.add( "http://download.pchome.net/wallpaper/pic-9468-1.jpg" );
         images.add( "http://img1.3lian.com/2015/w22/99/d/86.jpg" );
         return  images;
     }
}

最后,给上源码,下载地址( 下载源码): http://download.csdn.net/detail/u013365445/9608109
大家一起学习,哈。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值