Android实现自定义轮播图片控件详解
首先上效果图
实现原理
要完成一个轮播图片,首先想到的应该是使用viewpager
来实现。viewpager
已经有了滑动的功能,我们只要让它自己滚动。再加上下方的小圆点就行了。所以我们本次的自定义控件就是由viewpager
和linearlayout
叠加起来组成的。
一、创建一个自定义的viewpager
先上完整的代码
package com.kcode.autoscrollviewpager.view; import android.content.context; import android.os.message; import android.support.v4.view.viewpager; import android.util.attributeset; import android.util.log; import android.view.motionevent; import java.util.timer; import java.util.timertask; /** * created by caik on 2016/10/10. */ public class autoviewpager extends viewpager { private static final string tag = "autoviewpager"; private int currentitem; private timer mtimer; private autotask mtask; private boolean isfirst = true; public autoviewpager(context context) { super(context); } public autoviewpager(context context, attributeset attrs) { super(context, attrs); } public void start(){ if (mtimer == null) { mtimer = new timer(); } mtimer.schedule(new autotask(),3000,3000); } private runnable runnable = new runnable() { @override public void run() { currentitem = getcurrentitem(); if(currentitem == getadapter().getcount() - 1){ currentitem = 0 ; }else { currentitem++ ; } setcurrentitem(currentitem); } }; private autohandler mhandler = new autohandler(); public void updatepointview(int size) { if (getparent() instanceof autoscrollviewpager){ autoscrollviewpager pager = (autoscrollviewpager) getparent(); pager.initpointview(size); }else { log.e(tag,"parent view not be autoscrollviewpager"); } } public void onpageselected(int position) { autoscrollviewpager pager = (autoscrollviewpager) getparent(); pager.updatepointview(position); } private class autotask extends timertask{ @override public void run() { mhandler.post(runnable); } } private final static class autohandler extends android.os.handler{ @override public void handlemessage(message msg) { super.handlemessage(msg); } } public void onstop(){ //先取消定时器 if (mtimer != null) { mtimer.cancel(); mtimer = null; } } public void ondestroy(){ onstop(); } public void onresume(){ start(); } @override public boolean ontouchevent(motionevent ev) { switch (ev.getaction()){ case motionevent.action_down: log.i(tag,"down"); onstop(); break; case motionevent.action_move: log.i(tag,"move"); break; case motionevent.action_up: log.i(tag,"up"); onresume(); break; } return super.ontouchevent(ev); } }
autoviewpager 继承至viewpager,我们通过timer来启动一个定时器。
public void start(){ if (mtimer == null) { mtimer = new timer(); } mtimer.schedule(new autotask(),3000,3000); } private runnable runnable = new runnable() { @override public void run() { currentitem = getcurrentitem(); if(currentitem == getadapter().getcount() - 1){ currentitem = 0 ; }else { currentitem++ ; } setcurrentitem(currentitem); } };
每隔三秒去更新一下页面。这样就能起到一个自己滚动的效果。
二、设置adapter
要实现无限循环,只要把adapter中的getcount()
方法返回无限大,直接返回integer.max_value
就可以了。
完整的adapter代码:
package com.kcode.autoscrollviewpager.view; import android.content.context; import android.support.v4.view.pageradapter; import android.support.v4.view.viewpager; import android.view.layoutinflater; import android.view.view; import android.view.viewgroup; import android.widget.imageview; import com.kcode.autoscrollviewpager.r; import java.util.arraylist; import java.util.list; /** * created by caik on 2016/10/11. */ public abstract class baseviewpageradapter<t> extends pageradapter implements viewpager.onpagechangelistener{ private list<t> data = new arraylist<>(); private context mcontext; private autoviewpager mview; private onautoviewpageritemclicklistener listener; public baseviewpageradapter(list<t> t) { this.data = t; } public baseviewpageradapter(context context, autoviewpager viewpager) { this.mcontext = context; mview = viewpager; mview.setadapter(this); mview.addonpagechangelistener(this); mview.setcurrentitem(0); } public baseviewpageradapter(context context, autoviewpager viewpager,onautoviewpageritemclicklistener listener) { this.mcontext = context; mview = viewpager; this.listener = listener; mview.setadapter(this); mview.addonpagechangelistener(this); mview.setcurrentitem(0); } public baseviewpageradapter(context context, list<t> data,autoviewpager viewpager,onautoviewpageritemclicklistener listener) { this.mcontext = context; mview = viewpager; this.data = data; this.listener = listener; mview.setadapter(this); mview.addonpagechangelistener(this); mview.setcurrentitem(0); mview.start(); mview.updatepointview(getrealcount()); } public void add(t t){ data.add(t); notifydatasetchanged(); mview.updatepointview(getrealcount()); } @override public int getcount() { return data == null ? 0 : integer.max_value; } public int getrealcount(){ return data == null ? 0 : data.size(); } @override public void destroyitem(viewgroup container, int position, object object) { container.removeview((imageview) object); } @override public object instantiateitem(viewgroup container, final int position) { imageview view = (imageview) layoutinflater.from(mcontext) .inflate(r.layout.imageview,container,false); view.setonclicklistener(new view.onclicklistener() { @override public void onclick(view view) { if (listener != null) { listener.onitemclick(position % getrealcount(),data.get(position % getrealcount())); } } }); loadimage(view,position, data.get(position % getrealcount())); container.addview(view); return view; } public abstract void loadimage(imageview view,int position,t t); @override public boolean isviewfromobject(view view, object object) { return view == object; } @override public void onpagescrolled(int position, float positionoffset, int positionoffsetpixels) { } @override public void onpageselected(int position) { mview.onpageselected(position % getrealcount()); } @override public void onpagescrollstatechanged(int state) { } public interface onautoviewpageritemclicklistener<t> { void onitemclick(int position,t t); } }
这里我们使用了泛型,因为有时候我们可能只传一个url集合进来,也可能是对象集合,方便拓展。加载图片的方法也是一个抽象方法
public abstract void loadimage(imageview view,int position,t t);
因为每个app使用的图片加载框架都不一样,所以这里的加载就留个app自己实现。使用的时候创建adapter只要继承这里的baseviewpageradapter
,然后重写loadimage(imageview view,int position,t t)
方法,在这里进行图片的加载就行了。
如果你需不要底部的小圆点标示的话,这里就已经完成了。
使用的时候,直接使用
<com.kcode.autoscrollviewpager.view.autoviewpager android:layout_width="match_parent" android:layout_height="200dp"> </com.kcode.autoscrollviewpager.view.autoviewpager>
代替
<android.support.v4.view.viewpager android:layout_width="match_parent" android:layout_height="match_parent"> </android.support.v4.view.viewpager>
就可以了。需要底部的小圆点标示的话,继续往下
三、添加小圆点标示
需要添加小圆点标示的话。其实就是在viewpager上再加一层。我们新建一个view,继承至relativelayout
完整代码如下:
package com.kcode.autoscrollviewpager.view; import android.content.context; import android.util.attributeset; import android.view.viewgroup; import android.widget.imageview; import android.widget.linearlayout; import android.widget.relativelayout; import com.kcode.autoscrollviewpager.r; import static android.view.gravity.center; /** * created by caik on 2016/10/17. */ public class autoscrollviewpager extends relativelayout{ private autoviewpager mviewpager; private context mcontext; private linearlayout layout; public autoscrollviewpager(context context) { super(context); init(context); } public autoscrollviewpager(context context, attributeset attrs) { super(context, attrs); init(context); } private void init(context context){ mcontext = context; mviewpager = new autoviewpager(context); layout = new linearlayout(mcontext); addview(mviewpager); } public autoviewpager getviewpager() { return mviewpager; } public void initpointview(int size){ layout = new linearlayout(mcontext); for (int i = 0; i < size; i++) { imageview imageview = new imageview(mcontext); linearlayout.layoutparams params = new linearlayout.layoutparams(20,20); params.leftmargin = 8; params.gravity = center; imageview.setlayoutparams(params); if (i == 0) { imageview.setbackgroundresource(r.drawable.point_checked); }else { imageview.setbackgroundresource(r.drawable.point_normal); } layout.addview(imageview); } layoutparams layoutparams = new layoutparams(viewgroup.layoutparams.wrap_content, viewgroup.layoutparams.wrap_content); layoutparams.addrule(align_parent_bottom); layoutparams.addrule(align_parent_right); layoutparams.setmargins(12,20,12,20); layout.setlayoutparams(layoutparams); addview(layout); } public void updatepointview(int position) { int size = layout.getchildcount(); for (int i = 0; i < size; i++) { imageview imageview = (imageview) layout.getchildat(i); if (i == position){ imageview.setbackgroundresource(r.drawable.point_checked); }else { imageview.setbackgroundresource(r.drawable.point_normal); } } } }
初始化的时候创建一个viewpager
,一个linearlayout
(用来放小圆点)
public autoscrollviewpager(context context) { super(context); init(context); } public autoscrollviewpager(context context, attributeset attrs) { super(context, attrs); init(context); } private void init(context context){ mcontext = context; mviewpager = new autoviewpager(context); layout = new linearlayout(mcontext); addview(mviewpager); }
再通过addview(mviewpager);
添加。
需要准备两张图片,这里用shape进行绘制,shape的使用可以查看android shape使用.
初始化小圆点:
public void initpointview(int size){ layout = new linearlayout(mcontext); for (int i = 0; i < size; i++) { imageview imageview = new imageview(mcontext); linearlayout.layoutparams params = new linearlayout.layoutparams(20,20); params.leftmargin = 8; params.gravity = center; imageview.setlayoutparams(params); if (i == 0) { imageview.setbackgroundresource(r.drawable.point_checked); }else { imageview.setbackgroundresource(r.drawable.point_normal); } layout.addview(imageview); } layoutparams layoutparams = new layoutparams(viewgroup.layoutparams.wrap_content, viewgroup.layoutparams.wrap_content); layoutparams.addrule(align_parent_bottom); layoutparams.addrule(align_parent_right); layoutparams.setmargins(12,20,12,20); layout.setlayoutparams(layoutparams); addview(layout); }
更新小圆点:
public void updatepointview(int position) { int size = layout.getchildcount(); for (int i = 0; i < size; i++) { imageview imageview = (imageview) layout.getchildat(i); if (i == position){ imageview.setbackgroundresource(r.drawable.point_checked); }else { imageview.setbackgroundresource(r.drawable.point_normal); } } }
带小圆点的使用以下控件
<com.kcode.autoscrollviewpager.view.autoscrollviewpager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="220dp"> </com.kcode.autoscrollviewpager.view.autoscrollviewpager>
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。