Android实现Banner界面广告图片循环轮播(包括实现手动滑动循环)
程序员文章站
2024-02-22 09:23:28
前言:经常会看到有一些app的banner界面可以实现循环播放多个广告图片和手动滑动循环。本以为单纯的viewpager就可以实现这些功能。但是蛋疼的事情来了,...
前言:经常会看到有一些app的banner界面可以实现循环播放多个广告图片和手动滑动循环。本以为单纯的viewpager就可以实现这些功能。但是蛋疼的事情来了,viewpager并不支持循环翻页。所以要实现循环还得需要自己去动手。自己在网上也找了些例子,本博文的demo是结合自己找到的一些相关例子的基础上去改造,也希望对读者有用。
demo实现的效果图如下:
demo代码:
工程目录如下图:
废话不多说,上代码。
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界面广告图片循环轮播(包括实现手动滑动循环),希望对大家有所帮助!
下一篇: python入门教程之识别验证码