前言:经常会看到有一些app的banner界面可以实现循环播放多个广告图片和手动滑动循环。本以为单纯的viewpager就可以实现这些功能。但是蛋疼的事情来了,viewpager并不支持循环翻页。所以要实现循环还得需要自己去动手。自己在网上也找了些例子,本博文的demo是结合自己找到的一些相关例子的基础上去改造,也希望对读者有用。
demo实现的效果图如下:
demo代码:
工程目录如下图:
废话不多说,上代码。
1.主activity代码如下:
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
|
package com.stevenhu.android.phone.ui;
import java.util.arraylist;
import java.util.list;
import com.nostra13.universalimageloader.cache.disc.naming.md5filenamegenerator;
import com.nostra13.universalimageloader.core.displayimageoptions;
import com.nostra13.universalimageloader.core.imageloader;
import com.nostra13.universalimageloader.core.imageloaderconfiguration;
import com.nostra13.universalimageloader.core.assist.queueprocessingtype;
import com.stevenhu.android.phone.bean.adinfo;
import com.stevenhu.android.phone.utils.viewfactory;
import android.annotation.suppresslint;
import android.app.activity;
import android.os.bundle;
import android.view.view;
import android.widget.imageview;
import android.widget.toast;
import cn.androiddevelop.cycleviewpager.lib.cycleviewpager;
import cn.androiddevelop.cycleviewpager.lib.cycleviewpager.imagecycleviewlistener;
/**
* 描述:主页
*
* @author stevenhu
* @version 2015年5月8日 上午10:47:37
*/
public class mainactivity extends activity {
private list<imageview> views = new arraylist<imageview>();
private list<adinfo> infos = new arraylist<adinfo>();
private cycleviewpager cycleviewpager;
private string[] imageurls = { "http://img.taodiantong.cn/v55183/infoimg/2013-07/130720115322ky.jpg" ,
"http://pic30.nipic.com/20130626/8174275_085522448172_2.jpg" ,
"http://pic18.nipic.com/20111215/577405_080531548148_2.jpg" ,
"http://pic15.nipic.com/20110722/2912365_092519919000_2.jpg" ,
"http://pic.58pic.com/58pic/12/64/27/55u58picrdx.jpg" };
@override
protected void oncreate(bundle savedinstancestate) {
super .oncreate(savedinstancestate);
setcontentview(r.layout.ui_main);
configimageloader();
initialize();
}
@suppresslint ( "newapi" )
private void initialize() {
cycleviewpager = (cycleviewpager) getfragmentmanager()
.findfragmentbyid(r.id.fragment_cycle_viewpager_content);
for ( int i = 0 ; i < imageurls.length; i ++){
adinfo info = new adinfo();
info.seturl(imageurls[i]);
info.setcontent( "图片-->" + i );
infos.add(info);
}
// 将最后一个imageview添加进来
views.add(viewfactory.getimageview( this , infos.get(infos.size() - 1 ).geturl()));
for ( int i = 0 ; i < infos.size(); i++) {
views.add(viewfactory.getimageview( this , infos.get(i).geturl()));
}
// 将第一个imageview添加进来
views.add(viewfactory.getimageview( this , infos.get( 0 ).geturl()));
// 设置循环,在调用setdata方法前调用
cycleviewpager.setcycle( true );
// 在加载数据前设置是否循环
cycleviewpager.setdata(views, infos, madcycleviewlistener);
//设置轮播
cycleviewpager.setwheel( true );
// 设置轮播时间,默认5000ms
cycleviewpager.settime( 2000 );
//设置圆点指示图标组居中显示,默认靠右
cycleviewpager.setindicatorcenter();
}
private imagecycleviewlistener madcycleviewlistener = new imagecycleviewlistener() {
@override
public void onimageclick(adinfo info, int position, view imageview) {
if (cycleviewpager.iscycle()) {
position = position - 1 ;
toast.maketext(mainactivity. this ,
"position-->" + info.getcontent(), toast.length_short)
.show();
}
}
};
/**
* 配置imageloder
*/
private void configimageloader() {
// 初始化imageloader
@suppresswarnings ( "deprecation" )
displayimageoptions options = new displayimageoptions.builder().showstubimage(r.drawable.icon_stub) // 设置图片下载期间显示的图片
.showimageforemptyuri(r.drawable.icon_empty) // 设置图片uri为空或是错误的时候显示的图片
.showimageonfail(r.drawable.icon_error) // 设置图片加载或解码过程中发生错误显示的图片
.cacheinmemory( true ) // 设置下载的图片是否缓存在内存中
.cacheondisc( true ) // 设置下载的图片是否缓存在sd卡中
// .displayer(new roundedbitmapdisplayer(20)) // 设置成圆角图片
.build(); // 创建配置过得displayimageoption对象
imageloaderconfiguration config = new imageloaderconfiguration.builder(getapplicationcontext()).defaultdisplayimageoptions(options)
.threadpriority(thread.norm_priority - 2 ).denycacheimagemultiplesizesinmemory()
.disccachefilenamegenerator( new md5filenamegenerator()).tasksprocessingorder(queueprocessingtype.lifo).build();
imageloader.getinstance().init(config);
}
}
|
2.主文件ui_main.xml代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
<?xml version= "1.0" encoding= "utf-8" ?>
<linearlayout xmlns:android= "http://schemas.android.com/apk/res/android"
android:layout_width= "match_parent"
android:layout_height= "match_parent"
android:orientation= "vertical" >
<fragment
android:id= "@+id/fragment_cycle_viewpager_content"
android:name= "cn.androiddevelop.cycleviewpager.lib.cycleviewpager"
android:layout_width= "match_parent"
android:layout_height= "180dip" />
<relativelayout
android:layout_width= "fill_parent"
android:layout_height= "0dip"
android:layout_weight= "1" >
<textview
android:layout_width= "wrap_content"
android:layout_height= "wrap_content"
android:layout_centerinparent= "true"
android:text= "content" />
</relativelayout>
</linearlayout>
|
3.cycleviewpager类代码如下:
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
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
|
package cn.androiddevelop.cycleviewpager.lib;
import java.util.arraylist;
import java.util.list;
import android.annotation.suppresslint;
import android.app.fragment;
import android.os.bundle;
import android.os.message;
import android.support.v4.view.pageradapter;
import android.support.v4.view.viewpager.onpagechangelistener;
import android.view.layoutinflater;
import android.view.view;
import android.view.view.onclicklistener;
import android.view.viewgroup;
import android.widget.framelayout;
import android.widget.imageview;
import android.widget.linearlayout;
import android.widget.relativelayout;
import com.stevenhu.android.phone.bean.adinfo;
import com.stevenhu.android.phone.ui.r;
/**
* 实现可循环,可轮播的viewpager
*/
@suppresslint ( "newapi" )
public class cycleviewpager extends fragment implements onpagechangelistener {
private list<imageview> imageviews = new arraylist<imageview>();
private imageview[] indicators;
private framelayout viewpagerfragmentlayout;
private linearlayout indicatorlayout; // 指示器
private baseviewpager viewpager;
private baseviewpager parentviewpager;
private viewpageradapter adapter;
private cycleviewpagerhandler handler;
private int time = 5000 ; // 默认轮播时间
private int currentposition = 0 ; // 轮播当前位置
private boolean isscrolling = false ; // 滚动框是否滚动着
private boolean iscycle = false ; // 是否循环
private boolean iswheel = false ; // 是否轮播
private long releasetime = 0 ; // 手指松开、页面不滚动时间,防止手机松开后短时间进行切换
private int wheel = 100 ; // 转动
private int wheel_wait = 101 ; // 等待
private imagecycleviewlistener mimagecycleviewlistener;
private list<adinfo> infos;
@override
public view oncreateview(layoutinflater inflater, viewgroup container,
bundle savedinstancestate) {
view view = layoutinflater.from(getactivity()).inflate(
r.layout.view_cycle_viewpager_contet, null );
viewpager = (baseviewpager) view.findviewbyid(r.id.viewpager);
indicatorlayout = (linearlayout) view
.findviewbyid(r.id.layout_viewpager_indicator);
viewpagerfragmentlayout = (framelayout) view
.findviewbyid(r.id.layout_viewager_content);
handler = new cycleviewpagerhandler(getactivity()) {
@override
public void handlemessage(message msg) {
super .handlemessage(msg);
if (msg.what == wheel && imageviews.size() != 0 ) {
if (!isscrolling) {
int max = imageviews.size() + 1 ;
int position = (currentposition + 1 ) % imageviews.size();
viewpager.setcurrentitem(position, true );
if (position == max) { // 最后一页时回到第一页
viewpager.setcurrentitem( 1 , false );
}
}
releasetime = system.currenttimemillis();
handler.removecallbacks(runnable);
handler.postdelayed(runnable, time);
return ;
}
if (msg.what == wheel_wait && imageviews.size() != 0 ) {
handler.removecallbacks(runnable);
handler.postdelayed(runnable, time);
}
}
};
return view;
}
public void setdata(list<imageview> views, list<adinfo> list, imagecycleviewlistener listener) {
setdata(views, list, listener, 0 );
}
/**
* 初始化viewpager
*
* @param views
* 要显示的views
* @param showposition
* 默认显示位置
*/
public void setdata(list<imageview> views, list<adinfo> list, imagecycleviewlistener listener, int showposition) {
mimagecycleviewlistener = listener;
infos = list;
this .imageviews.clear();
if (views.size() == 0 ) {
viewpagerfragmentlayout.setvisibility(view.gone);
return ;
}
for (imageview item : views) {
this .imageviews.add(item);
}
int ivsize = views.size();
// 设置指示器
indicators = new imageview[ivsize];
if (iscycle)
indicators = new imageview[ivsize - 2 ];
indicatorlayout.removeallviews();
for ( int i = 0 ; i < indicators.length; i++) {
view view = layoutinflater.from(getactivity()).inflate(
r.layout.view_cycle_viewpager_indicator, null );
indicators[i] = (imageview) view.findviewbyid(r.id.image_indicator);
indicatorlayout.addview(view);
}
adapter = new viewpageradapter();
// 默认指向第一项,下方viewpager.setcurrentitem将触发重新计算指示器指向
setindicator( 0 );
viewpager.setoffscreenpagelimit( 3 );
viewpager.setonpagechangelistener( this );
viewpager.setadapter(adapter);
if (showposition < 0 || showposition >= views.size())
showposition = 0 ;
if (iscycle) {
showposition = showposition + 1 ;
}
viewpager.setcurrentitem(showposition);
}
/**
* 设置指示器居中,默认指示器在右方
*/
public void setindicatorcenter() {
relativelayout.layoutparams params = new relativelayout.layoutparams(
relativelayout.layoutparams.wrap_content,
relativelayout.layoutparams.wrap_content);
params.addrule(relativelayout.align_parent_bottom);
params.addrule(relativelayout.center_horizontal);
indicatorlayout.setlayoutparams(params);
}
/**
* 是否循环,默认不开启,开启前,请将views的最前面与最后面各加入一个视图,用于循环
*
* @param iscycle
* 是否循环
*/
public void setcycle( boolean iscycle) {
this .iscycle = iscycle;
}
/**
* 是否处于循环状态
*
* @return
*/
public boolean iscycle() {
return iscycle;
}
/**
* 设置是否轮播,默认不轮播,轮播一定是循环的
*
* @param iswheel
*/
public void setwheel( boolean iswheel) {
this .iswheel = iswheel;
iscycle = true ;
if (iswheel) {
handler.postdelayed(runnable, time);
}
}
/**
* 是否处于轮播状态
*
* @return
*/
public boolean iswheel() {
return iswheel;
}
final runnable runnable = new runnable() {
@override
public void run() {
if (getactivity() != null && !getactivity().isfinishing()
&& iswheel) {
long now = system.currenttimemillis();
// 检测上一次滑动时间与本次之间是否有触击(手滑动)操作,有的话等待下次轮播
if (now - releasetime > time - 500 ) {
handler.sendemptymessage(wheel);
} else {
handler.sendemptymessage(wheel_wait);
}
}
}
};
/**
* 释放指示器高度,可能由于之前指示器被限制了高度,此处释放
*/
public void releaseheight() {
getview().getlayoutparams().height = relativelayout.layoutparams.match_parent;
refreshdata();
}
/**
* 设置轮播暂停时间,即没多少秒切换到下一张视图.默认5000ms
*
* @param time
* 毫秒为单位
*/
public void settime( int time) {
this .time = time;
}
/**
* 刷新数据,当外部视图更新后,通知刷新数据
*/
public void refreshdata() {
if (adapter != null )
adapter.notifydatasetchanged();
}
/**
* 隐藏cycleviewpager
*/
public void hide() {
viewpagerfragmentlayout.setvisibility(view.gone);
}
/**
* 返回内置的viewpager
*
* @return viewpager
*/
public baseviewpager getviewpager() {
return viewpager;
}
/**
* 页面适配器 返回对应的view
*
* @author yuedong li
*
*/
private class viewpageradapter extends pageradapter {
@override
public int getcount() {
return imageviews.size();
}
@override
public boolean isviewfromobject(view arg0, object arg1) {
return arg0 == arg1;
}
@override
public void destroyitem(viewgroup container, int position, object object) {
container.removeview((view) object);
}
@override
public view instantiateitem(viewgroup container, final int position) {
imageview v = imageviews.get(position);
if (mimagecycleviewlistener != null ) {
v.setonclicklistener( new onclicklistener() {
@override
public void onclick(view v) {
mimagecycleviewlistener.onimageclick(infos.get(currentposition - 1 ), currentposition, v);
}
});
}
container.addview(v);
return v;
}
@override
public int getitemposition(object object) {
return position_none;
}
}
@override
public void onpagescrollstatechanged( int arg0) {
if (arg0 == 1 ) { // viewpager在滚动
isscrolling = true ;
return ;
} else if (arg0 == 0 ) { // viewpager滚动结束
if (parentviewpager != null )
parentviewpager.setscrollable( true );
releasetime = system.currenttimemillis();
viewpager.setcurrentitem(currentposition, false );
}
isscrolling = false ;
}
@override
public void onpagescrolled( int arg0, float arg1, int arg2) {
}
@override
public void onpageselected( int arg0) {
int max = imageviews.size() - 1 ;
int position = arg0;
currentposition = arg0;
if (iscycle) {
if (arg0 == 0 ) {
currentposition = max - 1 ;
} else if (arg0 == max) {
currentposition = 1 ;
}
position = currentposition - 1 ;
}
setindicator(position);
}
/**
* 设置viewpager是否可以滚动
*
* @param enable
*/
public void setscrollable( boolean enable) {
viewpager.setscrollable(enable);
}
/**
* 返回当前位置,循环时需要注意返回的position包含之前在views最前方与最后方加入的视图,即当前页面试图在views集合的位置
*
* @return
*/
public int getcurrentpostion() {
return currentposition;
}
/**
* 设置指示器
*
* @param selectedposition
* 默认指示器位置
*/
private void setindicator( int selectedposition) {
for ( int i = 0 ; i < indicators.length; i++) {
indicators[i]
.setbackgroundresource(r.drawable.icon_point);
}
if (indicators.length > selectedposition)
indicators[selectedposition]
.setbackgroundresource(r.drawable.icon_point_pre);
}
/**
* 如果当前页面嵌套在另一个viewpager中,为了在进行滚动时阻断父viewpager滚动,可以 阻止父viewpager滑动事件
* 父viewpager需要实现parentviewpager中的setscrollable方法
*/
public void disableparentviewpagertouchevent(baseviewpager parentviewpager) {
if (parentviewpager != null )
parentviewpager.setscrollable( false );
}
/**
* 轮播控件的监听事件
*
* @author minking
*/
public static interface imagecycleviewlistener {
/**
* 单击图片事件
*
* @param position
* @param imageview
*/
public void onimageclick(adinfo info, int postion, view imageview);
}
}
|
cycleviewpager类为实现可循环,可轮播的viewpager的核心类,继承自fragment,具体实现原理就不多说了,代码中都有相关的注释。
以上所述是小编给大家介绍的android实现banner界面广告图片循环轮播(包括实现手动滑动循环),希望对大家有所帮助!