Android Viewpager实现无限循环轮播图
在网上找了很多viewpager实现图片轮播的,但是大多数通过以下方式在pageradapter的getcount()返回一个无限大的数,来实现 伪无限
@override public int getcount() { return integer.max_value;//返回一个无限大的值,可以 无限循环 }
虽然通过这种方式是能达到效果,但是从严格意义上来说并不是真正的无限。
假如有五张轮播图 item的编号为(0,1,2,3,4) 要想实现 无限循环 我们在这五张的头部和尾部各加一张即(5+2)张,item编号为(0,1,2,3,4,5,6)其中编号为0,6的两张不做展示只是为了做循环轮播的铺垫,使得播放更加平滑。
1、当我们从编号为5 右滑的时候到了编号6 这时候就将当前页面设置为1
2、当我们从编号为1左滑的时候到了编号0 这时候就将当前页面设置为5
这么做之后就可以实现无限轮播 怎么保证从编号6跳转编号1的时候不出现页面停顿 突然跳到下一页的现象呢?
public object instantiateitem (viewgroup container, int position)
在指定的位置创建页面;适配器负责添加view到这个容器中,然而它只保证在finishupdate(viewgroup)返回时才完成。
public void destroyitem (viewgroup container, int position, object object)
删除指定位置的页面;适配器负责从view容器中删除view,然而它只保证在finishupdate(viewgroup)返回时才完成。
所以说 重点就在于finishupdate(viewgroup)这个方法 其实无论是创建view添加到容器中 还是 销毁view 都是在此方法结束之后执行的
换句话说 就是 我在这个方法里让页面完成从 编号5跳转到编号1 或者从编号1跳转到编号5,此方法完成时 视图还未完成创建或者 销毁 这样也就不会出现 页面停顿 突然跳到下一页的现象。
@override public void finishupdate(viewgroup container) { super.finishupdate(container); int position = viewpager.getcurrentitem(); if (position == 0) { position = simpledraweeviewlist.size() - 2; viewpager.setcurrentitem(position,false); } else if (position == simpledraweeviewlist.size() - 1) { position = 1; viewpager.setcurrentitem(position,false); } }
话不多说,上代码:
布局文件:
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.constraintlayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".mainactivity"> <framelayout android:id="@+id/framelayout" android:layout_width="0dp" android:layout_height="200dp" app:layout_constraintend_toendof="parent" app:layout_constrainthorizontal_bias="0.0" app:layout_constraintstart_tostartof="parent" app:layout_constrainttop_totopof="parent"> <android.support.v4.view.viewpager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="match_parent" tools:layout_editor_absolutex="8dp" tools:layout_editor_absolutey="0dp" /> <linearlayout android:layout_width="match_parent" android:layout_height="35dip" android:layout_gravity="bottom" android:background="#33000000" android:gravity="center_vertical" android:orientation="horizontal" android:weightsum="10"> <textview android:id="@+id/tv_pager_title" android:layout_width="0dp" android:layout_height="35dip" android:layout_weight="8" android:gravity="center_vertical" android:paddingleft="8dip" android:text="加载图片轮播失败" android:textcolor="@android:color/white" /> <linearlayout android:id="@+id/linelayout_dot" android:layout_width="0dp" android:layout_height="match_parent" android:layout_marginright="5dp" android:layout_weight="2" android:gravity="center|right" android:orientation="horizontal" android:paddingleft="3dp" android:paddingright="3dp" /> </linearlayout> </framelayout> </android.support.constraint.constraintlayout>
最主要的pageradapter:
import android.content.context; import android.support.v4.view.pageradapter; import android.support.v4.view.viewpager; import android.util.log; import android.view.view; import android.view.viewgroup; import com.facebook.drawee.view.simpledraweeview; import java.util.list; public class imagespageradapter extends pageradapter { private list<simpledraweeview> simpledraweeviewlist; private viewpager viewpager; private context context; private simpledraweeview simpledraweeview; public imagespageradapter(list<simpledraweeview> simpledraweeviewlist, viewpager viewpager, context context) { this.simpledraweeviewlist = simpledraweeviewlist; this.viewpager = viewpager; this.context = context; } @override public int getcount() { return simpledraweeviewlist.size(); } //删除指定位置的页面;适配器负责从view容器中删除view,然而它只保证在finishupdate(viewgroup)返回时才完成。 @override public void destroyitem(viewgroup container, int position, object object) { // 把imageview从viewpager中移除掉 viewpager.removeview(simpledraweeviewlist.get(position)); //super.destroyitem(container, position, object); } //是否获取缓存 @override public boolean isviewfromobject(view view, object object) { return view == object; } //实例化item //在指定的位置创建页面;适配器负责添加view到这个容器中,然而它只保证在finishupdate(viewgroup)返回时才完成。 @override public object instantiateitem(viewgroup container, int position) { simpledraweeview = simpledraweeviewlist.get(position); viewpager.addview(simpledraweeview); return simpledraweeview; } @override public int getitemposition(object object) { return position_none; } //无论是创建view添加到容器中 还是 销毁view 都是在此方法结束之后执行的 @override public void finishupdate(viewgroup container) { super.finishupdate(container); int position = viewpager.getcurrentitem(); if (position == 0) { position = simpledraweeviewlist.size() - 2; viewpager.setcurrentitem(position,false); } else if (position == simpledraweeviewlist.size() - 1) { position = 1; viewpager.setcurrentitem(position,false); } } /* private int mchildcount = 0; @override public void notifydatasetchanged() { mchildcount = getcount(); super.notifydatasetchanged(); } @override public int getitemposition(object object) { if (mchildcount > 0) { mchildcount--; log.e("image","getitemposition"); return position_none; } return super.getitemposition(object); }*/ }
import android.app.activity; import android.content.context; import android.graphics.drawable.drawable; import android.support.v4.content.contextcompat; import android.support.v4.view.viewpager; import android.util.log; import android.view.view; import android.view.viewgroup; import android.widget.linearlayout; import android.widget.textview; import com.facebook.drawee.view.simpledraweeview; import java.util.arraylist; import java.util.list; public class imagecarousel { private context context; private viewpager viewpager; private textview tvtitle; private linearlayout dotsroot; private int time; private list<view> dots;//小点 private int previousposition = 1;//前一个被选中的position private list<simpledraweeview> simpledraweeviewlist; private string[] titles;//标题数组 private imagespageradapter adapter; private autoplaythread autoplaythread; private volatile boolean isexit = true; private static final int first_page = 1; public imagecarousel(context context, viewpager viewpager, textview tvtitle, list<view> dots, int time) { this.context = context; this.viewpager = viewpager; this.tvtitle = tvtitle; this.dots = dots; this.time = time; log.e("image", "构造方法"); } /** * 传入数据 * * @param simpledraweeviewlist simpledraweeview集合 * @param titles 标题数组 * @return this 本身 */ public imagecarousel init(list<simpledraweeview> simpledraweeviewlist, string[] titles) { this.simpledraweeviewlist = simpledraweeviewlist; this.titles = titles; log.e("image", "init"); autoplaythread = new autoplaythread(); return this; } /** * 重新加载,有待考验... * * @param simpledraweeviewlist simpledraweeview集合 * @param titles 标题数组 */ public void reload(list<simpledraweeview> simpledraweeviewlist, string[] titles) { init(simpledraweeviewlist, titles); previousposition = 0; start(); } /** * 设置设配器,并实现轮播功能 */ public void start() { if (adapter != null) { adapter = null; } adapter = new imagespageradapter(this.simpledraweeviewlist, viewpager, context); viewpager.setadapter(adapter); viewpager.addonpagechangelistener(new viewpager.onpagechangelistener() { @override public void onpagescrolled(int position, float positionoffset, int positionoffsetpixels) { } //当被选择 @override public void onpageselected(int position) { int currentposition = 1; if (position == simpledraweeviewlist.size() - 1) { // 设置当前值为1 currentposition = first_page; } else if (position == 0) { // 如果索引值为0了,就设置索引值为倒数第二个 currentposition = simpledraweeviewlist.size() - 2; } else { currentposition = position; } // 把当前选中的点给切换了, 还有描述信息也切换 tvtitle.settext(titles[currentposition]);//图片下面设置显示文本 //设置轮播点 可设置成传入的图 log.d("dots", "previousposition=" + previousposition + " currentposition=" + currentposition); dots.get(previousposition-1).setbackgroundresource(r.drawable.ic_dot_focused); dots.get(currentposition-1).setbackgroundresource(r.drawable.ic_dot_normal); // 把当前的索引赋值给前一个索引变量, 方便下一次再切换. previousposition = currentposition; } @override public void onpagescrollstatechanged(int state) { // scroll_state_idle :空闲状态 // scroll_state_dragging :滑动状态 // scroll_state_settling :滑动后滑翔的状态 if (state == viewpager.scroll_state_dragging) { } else if(state == viewpager.scroll_state_idle){ } } }); setfirstlocation(); //autoplaythread.start(); } /** * 设置刚打开app时显示的图片和文字 */ private void setfirstlocation() { tvtitle.settext(titles[0]); dots.get(0).setbackgroundresource(r.drawable.ic_dot_normal); viewpager.setcurrentitem(1); } /** * 设置是否轮播 * * @param b */ private void setautoplay(boolean b) { /*if (b && suspendrequested) { autoplaythread.requestresume(); } else if (!b){ autoplaythread.requestsuspend(); }*/ } public void stopautoplay() { if (autoplaythread != null) { log.e("thrad", "暂停"); isexit = true; autoplaythread.interrupt(); autoplaythread = null; } } /** * 请求继续 */ public void startautoplay() { log.e("thrad", "开始"); isexit = false; autoplaythread = null; autoplaythread = new autoplaythread(); autoplaythread.start(); } /** * 自动播放线程,添加暂停和继续方法 */ class autoplaythread extends thread { @override public synchronized void run() { while (!isexit) { try { thread.sleep(time); } catch (interruptedexception e) { log.e("thrad", "强制请求退出线程"); break; } ((activity) context).runonuithread(new runnable() { @override public void run() { viewpager.setcurrentitem(viewpager.getcurrentitem() + 1); } }); if (this.interrupted()) { log.e("thrad", "已经是停止状态了,我要退出了"); break; } } } } }
mainactivity.java:
import android.app.activity; import android.content.context; import android.graphics.drawable.drawable; import android.net.uri; import android.support.v4.content.contextcompat; import android.support.v4.view.viewpager; import android.support.v7.app.appcompatactivity; import android.os.bundle; import android.view.view; import android.view.viewgroup; import android.widget.abslistview; import android.widget.linearlayout; import android.widget.textview; import com.facebook.drawee.backends.pipeline.fresco; import com.facebook.drawee.backends.pipeline.pipelinedraweecontroller; import com.facebook.drawee.drawable.scalingutils; import com.facebook.drawee.generic.genericdraweehierarchy; import com.facebook.drawee.generic.genericdraweehierarchybuilder; import com.facebook.drawee.view.simpledraweeview; import com.facebook.imagepipeline.common.resizeoptions; import com.facebook.imagepipeline.request.imagerequest; import com.facebook.imagepipeline.request.imagerequestbuilder; import java.util.arraylist; import java.util.list; public class mainactivity extends appcompatactivity implements view.onclicklistener { // 图片轮播控件 private viewpager mviewpager; private textview mtvpagertitle; private linearlayout mlinelayoutdot; private imagecarousel imagecarousel; private list<view> dots;//小点 // 图片数据,包括图片标题、图片链接、数据、点击要打开的网站(点击打开的网页或一些提示指令) private list<imageinfo> imageinfolist; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); initview(); initevent(); imagestart(); } @override public void onclick(view v) { } /** * 初始化事件 * 左右多添加一张图片 */ private void initevent() { imageinfolist = new arraylist<>(); imageinfolist.add(new imageinfo(1, "图片5,公告5啦啦啦啦", "", "http://e.hiphotos.baidu.com/image/h%3d300/sign=73443062281f95cab9f594b6f9177fc5/72f082025aafa40fafb5fbc1a664034f78f019be.jpg", "")); imageinfolist.add(new imageinfo(2, "图片1,公告1啦啦啦啦", "", "http://d.hiphotos.baidu.com/image/pic/item/6159252dd42a2834a75bb01156b5c9ea15cebf2f.jpg", "")); imageinfolist.add(new imageinfo(3, "图片2,公告2啦啦啦啦", "", "http://c.hiphotos.baidu.com/image/h%3d300/sign=cfce96dfa251f3dedcb2bf64a4eff0ec/4610b912c8fcc3ce912597269f45d688d43f2039.jpg", "")); imageinfolist.add(new imageinfo(4, "图片3,公告3啦啦啦啦", "", "http://e.hiphotos.baidu.com/image/pic/item/6a600c338744ebf85ed0ab2bd4f9d72a6059a705.jpg", "")); imageinfolist.add(new imageinfo(5, "图片4,公告4啦啦啦啦", "", "http://b.hiphotos.baidu.com/image/h%3d300/sign=8ad802f3801001e9513c120f880e7b06/a71ea8d3fd1f4134be1e4e64281f95cad1c85efa.jpg", "")); imageinfolist.add(new imageinfo(6, "图片5,公告5啦啦啦啦", "", "http://e.hiphotos.baidu.com/image/h%3d300/sign=73443062281f95cab9f594b6f9177fc5/72f082025aafa40fafb5fbc1a664034f78f019be.jpg", "")); imageinfolist.add(new imageinfo(7, "图片1,公告1啦啦啦啦", "", "http://d.hiphotos.baidu.com/image/pic/item/6159252dd42a2834a75bb01156b5c9ea15cebf2f.jpg", "")); } /** * 初始化控件 */ private void initview() { mviewpager = findviewbyid(r.id.viewpager); mtvpagertitle = findviewbyid(r.id.tv_pager_title); mlinelayoutdot = findviewbyid(r.id.linelayout_dot); } private void imagestart() { //设置图片轮播 int[] imgaeids = new int[]{r.id.pager_image1, r.id.pager_image2, r.id.pager_image3, r.id.pager_image4, r.id.pager_image5, r.id.pager_image6, r.id.pager_image7, r.id.pager_image8}; string[] titles = new string[imageinfolist.size()]; list<simpledraweeview> simpledraweeviewlist = new arraylist<>(); for (int i = 0; i < imageinfolist.size(); i++) { titles[i] = imageinfolist.get(i).gettitle(); simpledraweeview simpledraweeview = new simpledraweeview(this); simpledraweeview.setaspectratio(1.78f); // 设置一张默认的图片 genericdraweehierarchy hierarchy = new genericdraweehierarchybuilder(this.getresources()) .setplaceholderimage(contextcompat.getdrawable(this, r.drawable.defult), scalingutils.scaletype.center_crop).build(); simpledraweeview.sethierarchy(hierarchy); simpledraweeview.setlayoutparams(new abslistview.layoutparams(abslistview.layoutparams.match_parent, abslistview.layoutparams.wrap_content)); //加载高分辨率图片; imagerequest imagerequest = imagerequestbuilder.newbuilderwithsource(uri.parse(imageinfolist.get(i).getimage())) .setresizeoptions(new resizeoptions(1280, 720)) .build(); pipelinedraweecontroller controller = (pipelinedraweecontroller) fresco.newdraweecontrollerbuilder() //.setlowresimagerequest(imagerequest.fromuri(uri.parse(listitembean.test_pic_low))) //在加载高分辨率图片之前加载低分辨率图片 .setimagerequest(imagerequest) .setoldcontroller(simpledraweeview.getcontroller()) .build(); simpledraweeview.setcontroller(controller); simpledraweeview.setid(imgaeids[i]);//给view设置id simpledraweeview.settag(imageinfolist.get(i)); simpledraweeview.setonclicklistener(this); titles[i] = imageinfolist.get(i).gettitle(); simpledraweeviewlist.add(simpledraweeview); } dots = adddots(mlinelayoutdot, fromrestodrawable(this, r.drawable.ic_dot_focused), simpledraweeviewlist.size()); imagecarousel = new imagecarousel(this, mviewpager, mtvpagertitle, dots, 5000); imagecarousel.init(simpledraweeviewlist, titles) .startautoplay(); imagecarousel.start(); } /** * 动态添加一个点 * * @param linearlayout 添加到linearlayout布局 * @param backgount 设置 * @return 小点的id */ private int adddot(final linearlayout linearlayout, drawable backgount) { final view dot = new view(this); linearlayout.layoutparams dotparams = new linearlayout.layoutparams(viewgroup.layoutparams.match_parent, viewgroup.layoutparams.wrap_content); dotparams.width = 16; dotparams.height = 16; dotparams.setmargins(4, 0, 4, 0); dot.setlayoutparams(dotparams); dot.setbackground(backgount); dot.setid(view.generateviewid()); ((activity) this).runonuithread(new runnable() { @override public void run() { linearlayout.addview(dot); } }); return dot.getid(); } /** * 资源图片转drawable * * @param context 上下文 * @param resid 资源id * @return 返回drawable图像 */ public static drawable fromrestodrawable(context context, int resid) { return contextcompat.getdrawable(context, resid); } /** * 添加多个轮播小点到横向线性布局 * * @param linearlayout 线性横向布局 * @param backgount 小点资源图标 * @param number 数量 * @return 返回小点view集合 */ private list<view> adddots(final linearlayout linearlayout, drawable backgount, int number) { list<view> dots = new arraylist<>(); for (int i = 2; i < number; i++) { // 注意这里的 i 从 2 开始,只画出5个点 int dotid = adddot(linearlayout, backgount); dots.add(findviewbyid(dotid)); } return dots; } }
ic_dot_focused.xml:
<vector android:height="5dp" android:viewportheight="24.0" android:viewportwidth="24.0" android:width="5dp" xmlns:android="http://schemas.android.com/apk/res/android"> <path android:fillcolor="#c8ffffff" android:pathdata="m12,12m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0"/> </vector>
ic_dot_normal.xml:
<vector android:height="5dp" android:viewportheight="24.0" android:viewportwidth="24.0" android:width="5dp" xmlns:android="http://schemas.android.com/apk/res/android"> <path android:fillcolor="#c8fd8888" android:pathdata="m12,12m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0"/> </vector>
当然这里主要是实现真正的无限轮播,其中对于 用户手动滑动图片时需要暂停轮播没有做相关处理。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
下一篇: 最靠谱的毕业旅行攻略