Android简单实现无限滚动自动滚动的ViewPager
程序员文章站
2024-02-25 19:17:15
经常我们会在应用中看到一个可以自动滚动,并且无限滚动的一个viewpager,百度谷歌上面也有很多关于这方面的教程,但是感觉都略显麻烦,而且封装的都不是很彻底。所以试着封装...
经常我们会在应用中看到一个可以自动滚动,并且无限滚动的一个viewpager,百度谷歌上面也有很多关于这方面的教程,但是感觉都略显麻烦,而且封装的都不是很彻底。所以试着封装一个比较好用的viewpager
效果如下:
简单的说一下实现思路,要实现无限滚动的话就要在pageradapter上面做一些手脚,在pageradapter的getcount的函数的返回值设置成integer.mxa_value就可以实现向右无限滚动,但是要实现向左无限滚动呢?就是一开始的时候setcurrentitem的时候设置一个非常大的值(大到你向左滚动了一万年还是有东西)
@override public int getcount() { return integer.max_value; }
mpager.setcurrentitem(10000 * mdatas.size());//一开始设置成这样的话就可以向左无限滚动了
然后另外一个就是底部的游标了:
底部的游标是用一个自定义视图:无非就是画一个背景,然后在画一个高亮的游标
/** * 指示游标 */ private class tipview extends view { private int mpadding; private int mcount; private int mcurpos; private paint mnorpaint;//未被选中的颜色 private paint mselpaint;//被选中的颜色 白色 private int mheight; public tipview(context context, int count) { super(context); mnorpaint = new paint(); mnorpaint.setantialias(true); int selheight = showutils.dip2px(2); int norheight = showutils.dip2px(1); mheight = showutils.dip2px(2); mnorpaint.setstrokewidth(norheight); mnorpaint.setcolor(color.argb(80, 255, 255, 255)); mselpaint = new paint(); mselpaint.setantialias(true); mselpaint.setstrokewidth(selheight); mselpaint.setcolor(color.white); mcount = count; mpadding = showutils.dip2px(0); } @override protected void ondraw(canvas canvas) { super.ondraw(canvas); int ow = (getwidth()-2 * mpadding)/ mcount; int y = getheight() / 2; canvas.drawline(mpadding, y, mcurpos * ow + mpadding, y, mnorpaint); canvas.drawline(mcurpos * ow + mpadding, y, (mcurpos + 1) * ow + mpadding, y, mselpaint); canvas.drawline((mcurpos + 1) * ow + mpadding, y, getwidth() - mpadding, y, mnorpaint); } @override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { viewgroup.layoutparams vp = getlayoutparams(); vp.width = viewgroup.layoutparams.match_parent; vp.height = mheight; super.onmeasure(widthmeasurespec, heightmeasurespec); } public void setcurpostion(int pos) { mcurpos = pos; invalidate(); } public void setcount(int count) { mcount = count; } }
r.layout.layout_recommend_item的布局:
<?xml version="1.0" encoding="utf-8"?> <relativelayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <imageview android:id="@+id/iv_pic" android:layout_width="match_parent" android:layout_height="match_parent" android:contentdescription="@null" android:scaletype="fitxy"/> <linearlayout android:layout_width="match_parent" android:layout_height="48dp" android:orientation="vertical" android:layout_alignparentbottom="true" android:background="@drawable/recommend" android:gravity="center"> <textview android:id="@+id/tv_desc" android:layout_width="match_parent" android:layout_height="wrap_content" android:textcolor="@color/white" android:textsize="@dimen/text_normal" android:maxlines="1" android:ellipsize="end" android:shadowcolor="#ff333333" android:shadowdx="2" android:shadowdy="2" android:paddingright="8dp" android:paddingleft="8dp" android:shadowradius="1" /> </linearlayout> </relativelayout>
还有一个是实现自动滚动,自动滚动的话就是监听onpagerchangelistener里面的函数,在viewpager状态改变的时候利用handler发送一个切换界面的消息:
@override public void onpagescrollstatechanged(int i) { curstate = i; if(i == viewpager.scroll_state_dragging){ //viewpager正在被拖动的时候 stopanimation(); }else { //没有可执行消息时候添加消息 实现自动滚动 if(!(shandler.hasmessages(start_scroll)&&shandler.hasmessages(scroll_next))){ startanimation(); } } } @override public void onpageselected(final int i) { //页面跳转后得到调用 shandler.removemessages(scroll_next); shandler.removemessages(start_scroll); if(curstate == viewpager.scroll_state_dragging){ return; } message msg = shandler.obtainmessage(scroll_next); msg.arg1 = i + 1; msg.obj = mpager; shandler.sendmessagedelayed(msg, show_time); mtipview.setcurpostion(i % mdatas.size()); }
整体的代码:
import android.content.context; import android.graphics.canvas; import android.graphics.color; import android.graphics.paint; import android.os.handler; import android.os.message; import android.support.v4.view.pageradapter; import android.support.v4.view.viewpager; import android.util.displaymetrics; import android.view.view; import android.view.viewgroup; import android.widget.imageview; import android.widget.relativelayout; import android.widget.textview; import com.nostra13.universalimageloader.core.displayimageoptions; import com.nostra13.universalimageloader.core.imageloader; import com.papau.show.r; import com.papau.show.entity.headviewentity; import com.papau.show.utils.showutils; import java.util.arraylist; import java.util.list; public class recommendview extends relativelayout implements irecommend { private static final int start_scroll = 1; private static final int scroll_next = 2; private static final int show_time = 5000; private list<headviewentity> mdatas = new arraylist<>(); private viewpager mpager; private context mcontext; private int mwidth, mheight; private imageloader mloader; private displayimageoptions moptions; private int mtitleheight; private tipview mtipview; private static handler shandler = new handler() { @override public void handlemessage(message msg) { int w = msg.what; viewpager pager = (viewpager) msg.obj; switch (w) { case start_scroll: pager.setcurrentitem(msg.arg1, true); break; case scroll_next: pager.setcurrentitem(msg.arg1, true); break; } } }; public recommendview(context context) { super(context); } public recommendview(context context, int w, int h) { super(context); mcontext = context; mwidth = w; mheight = h; initview(); // mpager.setadapter(new recommendadapter()); mpager.setonpagechangelistener(new monpagerchangelistener()); mloader = imageloadermanager.getimageloader(mcontext); moptions = imageloadermanager.getcacheondiskoptions(mcontext); init(); // displaymetrics dm = mcontext.getresources().getdisplaymetrics(); mtitleheight = showutils.dip2px(48);//设置游标高度 } @override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { viewgroup.layoutparams vp = getlayoutparams(); if (vp != null) { //设置视图的宽高 vp.width = mwidth; vp.height = mheight; } super.onmeasure(widthmeasurespec, heightmeasurespec); } private void initview() { mpager = new viewpager(mcontext); relativelayout.layoutparams rp = new relativelayout.layoutparams(relativelayout.layoutparams.match_parent, relativelayout.layoutparams.match_parent); addview(mpager, rp); } /** * 初始化指示游标 */ private void inittipview() { if (mtipview == null) { relativelayout.layoutparams rp = new relativelayout.layoutparams(10, 10); rp.addrule(relativelayout.align_parent_bottom);//显示在父控件的底部 rp.bottommargin = mtitleheight;//游标的高度 mtipview = new tipview(mcontext, mdatas.size()); addview(mtipview, rp); } else { mtipview.setcount(mdatas.size()); } } @override public void update() { getdata(); } @override public void init() { getdata(); } @override public void startanimation() { if (mdatas.size() == 0) { return; } message msg = shandler.obtainmessage(start_scroll); msg.obj = mpager; msg.arg1 = (mpager.getcurrentitem() + 1); shandler.sendmessagedelayed(msg, show_time); } @override public void stopanimation() { shandler.removemessages(start_scroll); shandler.removemessages(scroll_next); } /** * 获取viewpager要显示的数据 */ private void getdata() { string[] imagedata = new string[]{"http://f.hiphotos.baidu.com/image/h%3d360/sign=e105b9f1d61b0ef473e89e58edc651a1/b151f8198618367a9f738e022a738bd4b21ce573.jpg", "http://c.hiphotos.baidu.com/image/h%3d360/sign=b8cea9e92b738bd4db21b437918b876c/f7246b600c3387448982f948540fd9f9d72aa0bb.jpg", "http://a.hiphotos.baidu.com/image/h%3d360/sign=3da95d01e7dde711f8d245f097eecef4/71cf3bc79f3df8dc39cb6295cf11728b461028c4.jpg", "http://d.hiphotos.baidu.com/image/h%3d360/sign=410c3c96a60f4bfb93d09852334f788f/10dfa9ec8a136327a1de913a938fa0ec08fac78c.jpg", "http://e.hiphotos.baidu.com/image/h%3d360/sign=f6600b1613dfa9ece22e501152d1f754/342ac65c10385343ff41ee2b9113b07eca808829.jpg"}; for (int i = 0; i < 5; i++) { headviewentity info = new headviewentity(); info.setimageurl(imagedata[i]); info.settitle("我不做大哥好多年"+i); info.seturl("www.baidu.com"); mdatas.add(info); } shandler.postdelayed(new runnable() { @override public void run() { stopanimation(); inittipview(); mpager.setadapter(new recommendadapter()); mpager.setcurrentitem(10000 * mdatas.size());//一开始设置成这样的话就可以向左无限滚动了 } },2000); } /** * viewpager子项内容 */ private class recommendadapter extends pageradapter { /** * 填充子项视图的内容 * @param container 父控件 viewpager * @param position 子项的位置 * @return 返回子项视图 */ @override public object instantiateitem(viewgroup container, int position) { int curpos = position % mdatas.size(); view view = view.inflate(mcontext, r.layout.layout_recommend_item, null); viewgroup.layoutparams vp = new viewgroup.layoutparams(viewgroup.layoutparams.match_parent, viewgroup.layoutparams.match_parent); imageview iv = (imageview) view.findviewbyid(r.id.iv_pic); textview tv = (textview) view.findviewbyid(r.id.tv_desc); tv.settext(mdatas.get(curpos).gettitle()); mloader.displayimage(mdatas.get(curpos).getimageurl(), iv, moptions); container.addview(view, vp); view.settag(curpos); view.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { } }); return view; } @override public void destroyitem(viewgroup container, int position, object object) { container.removeview((view) object); } @override public int getcount() { return integer.max_value; } @override public boolean isviewfromobject(view view, object o) { return view == o; } } private class monpagerchangelistener implements viewpager.onpagechangelistener { private int curstate; @override public void onpagescrolled(int i, float v, int i1) { } @override public void onpagescrollstatechanged(int i) { curstate = i; if(i == viewpager.scroll_state_dragging){ //viewpager正在被拖动的时候 stopanimation(); }else { //没有可执行消息时候添加消息 实现自动滚动 if(!(shandler.hasmessages(start_scroll)&&shandler.hasmessages(scroll_next))){ startanimation(); } } } @override public void onpageselected(final int i) { //页面跳转后得到调用 shandler.removemessages(scroll_next); shandler.removemessages(start_scroll); if(curstate == viewpager.scroll_state_dragging){ return; } message msg = shandler.obtainmessage(scroll_next); msg.arg1 = i + 1; msg.obj = mpager; shandler.sendmessagedelayed(msg, show_time); mtipview.setcurpostion(i % mdatas.size()); } } /** * 指示游标 */ private class tipview extends view { private int mpadding; private int mcount; private int mcurpos; private paint mnorpaint;//未被选中的颜色 private paint mselpaint;//被选中的颜色 白色 private int mheight; public tipview(context context, int count) { super(context); mnorpaint = new paint(); mnorpaint.setantialias(true); int selheight = showutils.dip2px(2); int norheight = showutils.dip2px(1); mheight = showutils.dip2px(2); mnorpaint.setstrokewidth(norheight); mnorpaint.setcolor(color.argb(80, 255, 255, 255)); mselpaint = new paint(); mselpaint.setantialias(true); mselpaint.setstrokewidth(selheight); mselpaint.setcolor(color.white); mcount = count; mpadding = showutils.dip2px(0); } @override protected void ondraw(canvas canvas) { super.ondraw(canvas); int ow = (getwidth()-2 * mpadding)/ mcount; int y = getheight() / 2; canvas.drawline(mpadding, y, mcurpos * ow + mpadding, y, mnorpaint); canvas.drawline(mcurpos * ow + mpadding, y, (mcurpos + 1) * ow + mpadding, y, mselpaint); canvas.drawline((mcurpos + 1) * ow + mpadding, y, getwidth() - mpadding, y, mnorpaint); } @override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { viewgroup.layoutparams vp = getlayoutparams(); vp.width = viewgroup.layoutparams.match_parent; vp.height = mheight; super.onmeasure(widthmeasurespec, heightmeasurespec); } public void setcurpostion(int pos) { mcurpos = pos; invalidate(); } public void setcount(int count) { mcount = count; } } }
然后提供了一个接口调用:
/** * recommendview接口 */ public interface irecommend { void update(); void init(); void startanimation(); void stopanimation(); }
图片的加载用到了imageload库:
import android.content.context; import android.graphics.bitmap; import com.nostra13.universalimageloader.cache.disc.impl.unlimiteddiskcache; import com.nostra13.universalimageloader.core.displayimageoptions; import com.nostra13.universalimageloader.core.imageloader; import com.nostra13.universalimageloader.core.imageloaderconfiguration; import com.nostra13.universalimageloader.core.assist.imagescaletype; import com.papau.show.constant.constants; import java.io.file; public class imageloadermanager { /** * 不带硬盘缓存的options * * @param context * @return */ public static synchronized displayimageoptions getcacheonmemoryoptions(context context) { displayimageoptions options = new displayimageoptions.builder() .cacheinmemory(true) .cacheondisk(false) .imagescaletype(imagescaletype.exactly_stretched) .bitmapconfig(bitmap.config.argb_8888) // .showimageonloading( // context.getresources().getdrawable( // r.drawable.loading_wait)) // .showimageonfail( // context.getresources().getdrawable( // r.drawable.loading_wait)) .build(); return options; } public static synchronized displayimageoptions getcircleoptions(context context) { displayimageoptions options = new displayimageoptions.builder() .cacheinmemory(true) .cacheondisk(false) .imagescaletype(imagescaletype.exactly_stretched) .bitmapconfig(bitmap.config.argb_8888) // .showimageonloading( // context.getresources().getdrawable( // r.drawable.ic_user_head_hint)) // .showimageonfail( // context.getresources().getdrawable( // r.drawable.ic_user_head_hint)) .build(); return options; } /** * 获取在硬盘中缓存options * * @param context * @return options */ public static synchronized displayimageoptions getcacheondiskoptions( context context) { displayimageoptions options = new displayimageoptions.builder() .cacheinmemory(true) .cacheondisk(true) .imagescaletype(imagescaletype.exactly) .bitmapconfig(bitmap.config.argb_8888) // .showimageonloading( // context.getresources().getdrawable( // r.drawable.loading_wait)) // .showimageonfail( // context.getresources().getdrawable( // r.drawable.loading_wait)) .build(); return options; } /** * 获取imageloader 单例 * * @param context * @return */ public static synchronized imageloader getimageloader(context context) { imageloader imageloader = imageloader.getinstance(); file cachedir = new file(constants.spiccachelocalpath); imageloaderconfiguration config = new imageloaderconfiguration.builder( context).diskcache(new unlimiteddiskcache(cachedir)) .threadpoolsize(3) .diskcacheextraoptions(480, 320, null) .build(); imageloader.init(config); return imageloader; } }
使用方法
displaymetrics dm = getactivity().getresources().getdisplaymetrics(); recommendview rv = new recommendview(getactivity(),dm.widthpixels ,(dm.widthpixels)/2); headviewpager.addview(rv);
以上所述是小编给大家介绍的android简单实现无限滚动自动滚动的viewpager,希望对大家有所帮助
推荐阅读
-
Android简单实现无限滚动自动滚动的ViewPager
-
Android自定义ViewGroup实现受边界限制的滚动操作(3)
-
Android自定义ViewGroup实现可滚动的横向布局(2)
-
Android简单实现无限滚动自动滚动的ViewPager
-
最简单的方法实现去iframe滚动条 博客分类: jquery jQueryChromeCSSHTML
-
android使用 ScrollerView 实现 可上下滚动的分类栏实例
-
简单实现Android滚动公告栏
-
iOS UIScrollView滚动视图/无限循环滚动/自动滚动的实例代码
-
android使用 ScrollerView 实现 可上下滚动的分类栏实例
-
Android viewpager中动态添加view并实现伪无限循环的方法