欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android实现Banner界面广告图片循环轮播(包括实现手动滑动循环)

程序员文章站 2024-02-25 11:15:04
 前言:经常会看到有一些app的banner界面可以实现循环播放多个广告图片和手动滑动循环。本以为单纯的viewpager就可以实现这些功能。但是蛋疼的事情来了,...

 前言:经常会看到有一些app的banner界面可以实现循环播放多个广告图片和手动滑动循环。本以为单纯的viewpager就可以实现这些功能。但是蛋疼的事情来了,viewpager并不支持循环翻页。所以要实现循环还得需要自己去动手。自己在网上也找了些例子,本博文的demo是结合自己找到的一些相关例子的基础上去改造,也希望对读者有用。

demo实现的效果图如下:

Android实现Banner界面广告图片循环轮播(包括实现手动滑动循环)

demo代码:

工程目录如下图:

Android实现Banner界面广告图片循环轮播(包括实现手动滑动循环)

废话不多说,上代码。

1.主activity代码如下:

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代码如下:

<?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类代码如下:

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界面广告图片循环轮播(包括实现手动滑动循环),希望对大家有所帮助!