Android自定义组合控件之自定义下拉刷新和左滑删除实例代码
绪论
最近项目里面用到了下拉刷新和左滑删除,网上找了找并没有可以用的,有比较好的左滑删除,但是并没有和下拉刷新上拉加载结合到一起,要不就是一些比较水的结合,并不能在项目里面使用,小编一着急自己组合了一个,做完了和qq的对比了一下,并没有太大区别,今天分享给大家,其实并不难,但是不知道为什么网上没有比较好的demo,当你的项目真的很急的时候,又没有比较好的demo,那么“那条友谊的小船儿真是说翻就翻啊”,好了,下面先来具体看一下实现后的效果吧:
代码已经上传到github上了,小伙伴们记得star和follow哦
https://github.com/hankkin/swiperefreshdemo
还不错吧?比qq多了个上拉加载,好了看看怎么实现的吧,小编在之前的游客评论中了解到,代码注释很重要,所以尽量把注释写的很清楚:
实现思路
由于时间有限,左滑菜单是在网上找的demo
自定义下拉刷新头、尾
手势判断,根据滑动距离显示头部下拉布局
判断是否滑动到底部显示尾部上拉布局
创建左滑菜单,根据手势滑动事件弹出菜单
详细的看一下实现过程
1.首先我们先自定义下拉头布局:
<?xml version="1.0" encoding="utf-8"?> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="bottom" > <relativelayout android:id="@+id/xlistview_header_content" android:layout_width="fill_parent" android:background="#00000000" android:layout_height="60dp" > <linearlayout android:id="@+id/xlistview_header_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerinparent="true" android:gravity="center" android:orientation="vertical" > <textview android:id="@+id/xlistview_header_hint_textview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textcolor="#000" android:textsize="16sp" android:text="@string/xlistview_header_hint_normal" /> <linearlayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margintop="3dp" > <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:textcolor="#000" android:text="@string/xlistview_header_last_time" android:textsize="14sp" /> <textview android:id="@+id/xlistview_header_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textcolor="#000" android:textsize="14sp" /> </linearlayout> </linearlayout> <imageview android:id="@+id/xlistview_header_arrow" android:layout_width="wrap_content" android:layout_height="35dp" android:layout_alignleft="@id/xlistview_header_text" android:layout_centervertical="true" android:layout_marginleft="-50dp" android:src="@drawable/xlistview_arrow" /> <progressbar android:id="@+id/xlistview_header_progressbar" android:layout_width="25dp" android:layout_height="25dp" android:layout_alignleft="@id/xlistview_header_text" android:layout_centervertical="true" android:layout_marginleft="-55dp" android:visibility="gone"/> </relativelayout> </linearlayout>
2.接下来我们自定义headerview,代码很详细了,不多介绍了
package com.hankkin.library; import android.content.context; import android.util.attributeset; import android.view.gravity; import android.view.layoutinflater; import android.view.view; import android.view.animation.animation; import android.view.animation.rotateanimation; import android.widget.imageview; import android.widget.linearlayout; import android.widget.progressbar; import android.widget.textview; public class refreshlistheader extends linearlayout { //根布局 private linearlayout mcontainer; //下拉箭头图片 private imageview marrowimageview; //下拉进度条 private progressbar mprogressbar; //下拉文本 private textview mhinttextview; //状态值 0-正常 1-准备刷新 2-正在刷新 private int mstate = state_normal; //抬起动画 private animation mrotateupanim; //下拉动画 private animation mrotatedownanim; //下拉动画时间 private final int rotate_anim_duration = 180; public final static int state_normal = 0; public final static int state_ready = 1; public final static int state_refreshing = 2; public refreshlistheader(context context) { super(context); initview(context); } /** * @param context * @param attrs */ public refreshlistheader(context context, attributeset attrs) { super(context, attrs); initview(context); } /** * 初始化组件 * @param context */ private void initview(context context) { layoutparams lp = new layoutparams(layoutparams.fill_parent, 0); mcontainer = (linearlayout) layoutinflater.from(context).inflate(r.layout.xlistview_header, null); addview(mcontainer, lp); setgravity(gravity.bottom); marrowimageview = (imageview) findviewbyid(r.id.xlistview_header_arrow); mhinttextview = (textview) findviewbyid(r.id.xlistview_header_hint_textview); mprogressbar = (progressbar) findviewbyid(r.id.xlistview_header_progressbar); //设置抬起动画 mrotateupanim = new rotateanimation(0.0f, -180.0f, animation.relative_to_self, 0.5f, animation.relative_to_self, 0.5f); mrotateupanim.setduration(rotate_anim_duration); mrotateupanim.setfillafter(true); //设置下拉动画 mrotatedownanim = new rotateanimation(-180.0f, 0.0f, animation.relative_to_self, 0.5f, animation.relative_to_self, 0.5f); mrotatedownanim.setduration(rotate_anim_duration); mrotatedownanim.setfillafter(true); } //设置状态 public void setstate(int state) { if (state == mstate) return; //正在刷新时-显示进度条,隐藏下拉箭头 if (state == state_refreshing) { marrowimageview.clearanimation(); marrowimageview.setvisibility(view.invisible); mprogressbar.setvisibility(view.visible); } else { //显示下拉箭头,隐藏进度条 marrowimageview.setvisibility(view.visible); mprogressbar.setvisibility(view.invisible); } switch (state) { case state_normal: if (mstate == state_ready) {//准备刷新时开启动画 marrowimageview.startanimation(mrotatedownanim); } if (mstate == state_refreshing) {//正在刷新时开启动画 marrowimageview.clearanimation(); } mhinttextview.settext(r.string.xlistview_header_hint_normal); break; case state_ready: if (mstate != state_ready) { marrowimageview.clearanimation(); marrowimageview.startanimation(mrotateupanim); mhinttextview.settext(r.string.xlistview_header_hint_ready); } break; case state_refreshing: mhinttextview.settext(r.string.xlistview_header_hint_loading); break; default: } mstate = state; } /** * 设置头部高度 * @param height */ public void setvisiableheight(int height) { if (height < 0) height = 0; layoutparams lp = (layoutparams) mcontainer.getlayoutparams(); lp.height = height; mcontainer.setlayoutparams(lp); } public int getvisiableheight() { return mcontainer.getheight(); } 3.headerview定义结束后,我们需要自定义一个既支持下拉刷新又支持左滑删除的listview,看看我是怎么做的:(左滑菜单是引用网上的demo,代码写的也比较易懂,这里不详细给大家介绍了) 然后我们在他的基础上添加下拉上拉事件:(重点看一下ontouchevent事件) @override public boolean ontouchevent(motionevent ev) { if (mlasty == -1) { //获取上次y轴坐标 mlasty = ev.getrawy(); } switch (ev.getaction()) { case motionevent.action_down: //手势按下事件、获取坐标、设置上次下拉时间 firsttouchy = ev.getrawy(); mlasty = ev.getrawy(); setrefreshtime(refreshtime.getrefreshtime(getcontext())); int oldpos = mtouchposition; mdownx = ev.getx(); mdowny = ev.gety(); mtouchstate = touch_state_none; mtouchposition = pointtoposition((int) ev.getx(), (int) ev.gety()); //弹出左滑菜单 if (mtouchposition == oldpos && mtouchview != null && mtouchview.isopen()) { mtouchstate = touch_state_x; mtouchview.onswipe(ev);//左滑菜单手势监听事件,根据滑动距离弹出菜单 return true; } //获取item view,此方法是因为getchildat()传入index值导致listview不可见的item会报空指针 // 防止listview不可见的item获取到的为空,使用下面方法 view view = getchildat(mtouchposition - getfirstvisibleposition()); if (mtouchview != null && mtouchview.isopen()) {//如果滑动的item不为空并且已经开启,则关闭该菜单 mtouchview.smoothclosemenu(); mtouchview = null; return super.ontouchevent(ev); } if (mtouchview != null) {//否则打开左滑菜单 mtouchview.onswipe(ev); } if (view instanceof swipemenulayout) { mtouchview = (swipemenulayout) view; } break; case motionevent.action_move://手势滑动事件 final float deltay = ev.getrawy() - mlasty; float dy = math.abs((ev.gety() - mdowny)); float dx = math.abs((ev.getx() - mdownx)); mlasty = ev.getrawy(); //判断左滑菜单是否未激活、或者x轴偏移平方小于y轴偏移平方3倍的时候 if ((mtouchview == null || !mtouchview.isactive()) && math.pow(dx, 2) / math.pow(dy, 2) <= 3) { //判断第一个可见位置并且头部布局可见高度大于0时或者y轴偏移量>0 if (getfirstvisibleposition() == 0 && (mheaderview.getvisiableheight() > 0 || deltay > 0)) { // 重新更新头部高度 updateheaderheight(deltay / offset_radio); invokeonscrolling(); } } if (mtouchstate == touch_state_x) {//如果x轴偏移弹出左滑菜单 if (mtouchview != null) { mtouchview.onswipe(ev); } getselector().setstate(new int[] { 0 }); ev.setaction(motionevent.action_cancel); super.ontouchevent(ev); return true; } else if (mtouchstate == touch_state_none) { if (math.abs(dy) > max_y) { //如果y轴偏移量>指定y轴偏移量,设置y轴偏移状态 mtouchstate = touch_state_y; } else if (dx > max_x) {//如果x轴偏移量>指定x轴偏移量,设置x轴偏移状态,开始弹出左滑菜单 mtouchstate = touch_state_x; if (monswipelistener != null) { monswipelistener.onswipestart(mtouchposition); } } } break; case motionevent.action_up://手势抬起事件 mlasty = -1; // reset if (getfirstvisibleposition() == 0) { // 设置下拉刷新状态值,开启下拉刷新状态 if (menablepullrefresh && mheaderview.getvisiableheight() > mheaderviewheight) { mpullrefreshing = true; mheaderview.setstate(refreshlistheader.state_refreshing); if (onrefreshlistener != null) { tag=refresh; onrefreshlistener.onrefresh(); } } resetheaderheight(); } lasttouchy = ev.getrawy();//获取上次y轴偏移量 if (canloadmore()) {//判断是否满足上拉 loaddata(); } if (mtouchstate == touch_state_x) {//如果为x轴偏移状态,开启左滑 if (mtouchview != null) { mtouchview.onswipe(ev); if (!mtouchview.isopen()) { mtouchposition = -1; mtouchview = null; } } if (monswipelistener != null) { monswipelistener.onswipeend(mtouchposition); } ev.setaction(motionevent.action_cancel); super.ontouchevent(ev); return true; } break; } return super.ontouchevent(ev); }
当然这部分也是滑动冲突解决的主要部分,看一下完整的代码,应该能够看的懂了,小编几乎每一句都加上了注释,如果有看不明白的地方可以留言,小编会及时回复的:
package com.hankkin.library; import android.content.context; import android.os.asynctask; import android.util.attributeset; import android.util.typedvalue; import android.view.layoutinflater; import android.view.motionevent; import android.view.view; import android.view.viewtreeobserver.ongloballayoutlistener; import android.view.animation.decelerateinterpolator; import android.view.animation.interpolator; import android.widget.abslistview; import android.widget.abslistview.onscrolllistener; import android.widget.linearlayout; import android.widget.listadapter; import android.widget.listview; import android.widget.relativelayout; import android.widget.scroller; import android.widget.textview; import java.util.date; public class refreshswipemenulistview extends listview implements onscrolllistener { private static final int touch_state_none = 0; private static final int touch_state_x = 1; //x轴触摸状态值 private static final int touch_state_y = 2; //y轴触摸状态值 public static final int both=2;//上拉和下拉 public static final int header=0;//下拉 public static final int footer=1;//上拉 public static string tag;//listview的动作 public static final string refresh="refresh"; public static final string load="load"; private int max_y = 5; //y轴最大偏移量 private int max_x = 3; //x轴最大偏移量 private float mdownx; //触摸x private float mdowny; //触摸y private int mtouchstate; //触摸状态 private int mtouchposition; //触摸位置 private swipemenulayout mtouchview; //滑动弹出布局 private onswipelistener monswipelistener; //弹出监听器 private float firsttouchy; //第一次触摸y坐标 private float lasttouchy; //最后一次触摸y坐标 //创建左滑菜单接口 private swipemenucreator mmenucreator; //菜单点击事件 private onmenuitemclicklistener monmenuitemclicklistener; //关闭菜单动画修饰interpolator private interpolator mcloseinterpolator; //开启菜单动画修饰interpolator private interpolator mopeninterpolator; private float mlasty = -1; private scroller mscroller; private onscrolllistener mscrolllistener; // 滑动监听 // 下拉上拉监听器 private onrefreshlistener onrefreshlistener; //下拉头 private refreshlistheader mheaderview; //头部视图内容,用来计算头部高度,不下拉时隐藏 private relativelayout mheaderviewcontent; //下拉时间文本控件 private textview mheadertimeview; private int mheaderviewheight; // 头部高度 private boolean menablepullrefresh = true;//能否下拉刷新 private boolean mpullrefreshing = false; // 是否正在刷新 //上拉尾部视图 private linearlayout mfooterview; private boolean menablepullload;//是否可以上拉加载 private boolean mpullloading; //是否正在上拉 private boolean misfooterready = false; private int mtotalitemcount; private int mscrollback; private final static int scrollback_header = 0; private final static int scrollback_footer = 1; private final static int scroll_duration = 400; private final static int pull_load_more_delta = 50; private final static float offset_radio = 1.8f; private boolean isfootervisible=false; public refreshswipemenulistview(context context) { super(context); init(context); } public refreshswipemenulistview(context context, attributeset attrs, int defstyle) { super(context, attrs, defstyle); init(context); } public refreshswipemenulistview(context context, attributeset attrs) { super(context, attrs); init(context); } /** * 初始化组件 * @param context */ private void init(context context) { mscroller = new scroller(context, new decelerateinterpolator()); super.setonscrolllistener(this); // 初始化头部视图 mheaderview = new refreshlistheader(context); mheaderviewcontent = (relativelayout) mheaderview.findviewbyid(r.id.xlistview_header_content); mheadertimeview = (textview) mheaderview.findviewbyid(r.id.xlistview_header_time); addheaderview(mheaderview); // 初始化尾部视图 mfooterview = (linearlayout) layoutinflater.from(context).inflate(r.layout.xlistview_footer, null, false); // 初始化头部高度 mheaderview.getviewtreeobserver().addongloballayoutlistener(new ongloballayoutlistener() { @override public void ongloballayout() { mheaderviewheight = mheaderviewcontent.getheight(); //向 viewtreeobserver 注册方法,以获取控件尺寸 getviewtreeobserver().removeglobalonlayoutlistener(this); } }); max_x = dp2px(max_x); max_y = dp2px(max_y); mtouchstate = touch_state_none; } /** * 添加适配器 * @param adapter */ @override public void setadapter(listadapter adapter) { if (misfooterready == false) { //添加尾部隐藏 misfooterready = true; addfooterview(mfooterview); mfooterview.setvisibility(gone); } super.setadapter(new swipemenuadapter(getcontext(), adapter) { @override public void createmenu(swipemenu menu) {//创建左滑菜单 if (mmenucreator != null) { mmenucreator.create(menu); } } @override public void onitemclick(swipemenuview view, swipemenu menu, int index) { if (monmenuitemclicklistener != null) {//左滑菜单点击事件 monmenuitemclicklistener.onmenuitemclick(view.getposition(), menu, index); } if (mtouchview != null) { mtouchview.smoothclosemenu(); } } }); } public void setcloseinterpolator(interpolator interpolator) { mcloseinterpolator = interpolator; } public void setopeninterpolator(interpolator interpolator) { mopeninterpolator = interpolator; } public interpolator getopeninterpolator() { return mopeninterpolator; } public interpolator getcloseinterpolator() { return mcloseinterpolator; } @override public boolean onintercepttouchevent(motionevent ev) { return super.onintercepttouchevent(ev); } @override public boolean ontouchevent(motionevent ev) { if (mlasty == -1) { //获取上次y轴坐标 mlasty = ev.getrawy(); } switch (ev.getaction()) { case motionevent.action_down: //手势按下事件、获取坐标、设置上次下拉时间 firsttouchy = ev.getrawy(); mlasty = ev.getrawy(); setrefreshtime(refreshtime.getrefreshtime(getcontext())); int oldpos = mtouchposition; mdownx = ev.getx(); mdowny = ev.gety(); mtouchstate = touch_state_none; mtouchposition = pointtoposition((int) ev.getx(), (int) ev.gety()); //弹出左滑菜单 if (mtouchposition == oldpos && mtouchview != null && mtouchview.isopen()) { mtouchstate = touch_state_x; mtouchview.onswipe(ev);//左滑菜单手势监听事件,根据滑动距离弹出菜单 return true; } //获取item view,此方法是因为getchildat()传入index值导致listview不可见的item会报空指针 // 防止listview不可见的item获取到的为空,使用下面方法 view view = getchildat(mtouchposition - getfirstvisibleposition()); if (mtouchview != null && mtouchview.isopen()) {//如果滑动的item不为空并且已经开启,则关闭该菜单 mtouchview.smoothclosemenu(); mtouchview = null; return super.ontouchevent(ev); } if (mtouchview != null) {//否则打开左滑菜单 mtouchview.onswipe(ev); } if (view instanceof swipemenulayout) { mtouchview = (swipemenulayout) view; } break; case motionevent.action_move://手势滑动事件 final float deltay = ev.getrawy() - mlasty; float dy = math.abs((ev.gety() - mdowny)); float dx = math.abs((ev.getx() - mdownx)); mlasty = ev.getrawy(); //判断左滑菜单是否未激活、或者x轴偏移平方小于y轴偏移平方3倍的时候 if ((mtouchview == null || !mtouchview.isactive()) && math.pow(dx, 2) / math.pow(dy, 2) <= 3) { //判断第一个可见位置并且头部布局可见高度大于0时或者y轴偏移量>0 if (getfirstvisibleposition() == 0 && (mheaderview.getvisiableheight() > 0 || deltay > 0)) { // 重新更新头部高度 updateheaderheight(deltay / offset_radio); invokeonscrolling(); } } if (mtouchstate == touch_state_x) {//如果x轴偏移弹出左滑菜单 if (mtouchview != null) { mtouchview.onswipe(ev); } getselector().setstate(new int[] { 0 }); ev.setaction(motionevent.action_cancel); super.ontouchevent(ev); return true; } else if (mtouchstate == touch_state_none) { if (math.abs(dy) > max_y) { //如果y轴偏移量>指定y轴偏移量,设置y轴偏移状态 mtouchstate = touch_state_y; } else if (dx > max_x) {//如果x轴偏移量>指定x轴偏移量,设置x轴偏移状态,开始弹出左滑菜单 mtouchstate = touch_state_x; if (monswipelistener != null) { monswipelistener.onswipestart(mtouchposition); } } } break; case motionevent.action_up://手势抬起事件 mlasty = -1; // reset if (getfirstvisibleposition() == 0) { // 设置下拉刷新状态值,开启下拉刷新状态 if (menablepullrefresh && mheaderview.getvisiableheight() > mheaderviewheight) { mpullrefreshing = true; mheaderview.setstate(refreshlistheader.state_refreshing); if (onrefreshlistener != null) { tag=refresh; onrefreshlistener.onrefresh(); } } resetheaderheight(); } lasttouchy = ev.getrawy();//获取上次y轴偏移量 if (canloadmore()) {//判断是否满足上拉 loaddata(); } if (mtouchstate == touch_state_x) {//如果为x轴偏移状态,开启左滑 if (mtouchview != null) { mtouchview.onswipe(ev); if (!mtouchview.isopen()) { mtouchposition = -1; mtouchview = null; } } if (monswipelistener != null) { monswipelistener.onswipeend(mtouchposition); } ev.setaction(motionevent.action_cancel); super.ontouchevent(ev); return true; } break; } return super.ontouchevent(ev); } class resetheaderheighttask extends asynctask<void, void, void> { protected void doinbackground(void... params) { try { thread.sleep(400); } catch (interruptedexception e) { e.printstacktrace(); } return null; } protected void onpostexecute(void result) { mpullrefreshing = false; mheaderview.setstate(refreshlistheader.state_normal); resetheaderheight(); } } public void smoothopenmenu(int position) { if (position >= getfirstvisibleposition() && position <= getlastvisibleposition()) { view view = getchildat(position - getfirstvisibleposition()); if (view instanceof swipemenulayout) { mtouchposition = position; if (mtouchview != null && mtouchview.isopen()) { mtouchview.smoothclosemenu(); } mtouchview = (swipemenulayout) view; mtouchview.smoothopenmenu(); } } } private int dp2px(int dp) { return (int) typedvalue.applydimension(typedvalue.complex_unit_dip, dp, getcontext().getresources().getdisplaymetrics()); } public void setmenucreator(swipemenucreator menucreator) { this.mmenucreator = menucreator; } public void setonmenuitemclicklistener(onmenuitemclicklistener onmenuitemclicklistener) { this.monmenuitemclicklistener = onmenuitemclicklistener; } public void setonswipelistener(onswipelistener onswipelistener) { this.monswipelistener = onswipelistener; } public static interface onmenuitemclicklistener { void onmenuitemclick(int position, swipemenu menu, int index); } public static interface onswipelistener { void onswipestart(int position); void onswipeend(int position); } /** * 设置刷新可用 * @param enable */ private void setpullrefreshenable(boolean enable) { menablepullrefresh = enable; if (!menablepullrefresh) { // disable, hide the content mheaderviewcontent.setvisibility(view.invisible); } else { mheaderviewcontent.setvisibility(view.visible); } } /** * enable or disable pull up load more feature. * 设置加载可用 * @param enable */ private void setpullloadenable(boolean enable) { menablepullload = enable; if (!menablepullload) { mfooterview.setvisibility(gone); mfooterview.setonclicklistener(null); } else { mpullloading = false; mfooterview.setvisibility(visible); // both "pull up" and "click" will invoke load more. mfooterview.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { startloadmore(); } }); } } /** * stop refresh, reset header view. * 停止刷新,重置头部控件 */ private void stoprefresh() { if (mpullrefreshing == true) { mpullrefreshing = false; resetheaderheight(); } } /** * stop load more, reset footer view. * 停止加载更多,重置尾部控件 */ private void stoploadmore() { if (mpullloading == true) { mpullloading = false; mfooterview.setvisibility(gone); } } /** * set last refresh time * * @param time */ public void setrefreshtime(string time) { mheadertimeview.settext(time); } private void invokeonscrolling() { if (mscrolllistener instanceof onxscrolllistener) { onxscrolllistener l = (onxscrolllistener) mscrolllistener; l.onxscrolling(this); } } /** * 更新头部高度,设置状态值 * @param delta */ private void updateheaderheight(float delta) { mheaderview.setvisiableheight((int) delta + mheaderview.getvisiableheight()); if (menablepullrefresh && !mpullrefreshing) { if (mheaderview.getvisiableheight() > mheaderviewheight) { mheaderview.setstate(refreshlistheader.state_ready); } else { mheaderview.setstate(refreshlistheader.state_normal); } } setselection(0); // scroll to top each time } /** * 重置头部视图高度 */ private void resetheaderheight() { int height = mheaderview.getvisiableheight(); if (height == 0) // 不可见 return; // 如果正在刷新并且头部高度没有完全显示不做操作 if (mpullrefreshing && height <= mheaderviewheight) { return; } int finalheight = 0; // 默认 //如果正在刷新并且滑动高度大于头部高度 if (mpullrefreshing && height > mheaderviewheight) { finalheight = mheaderviewheight; } mscrollback = scrollback_header; mscroller.startscroll(0, height, 0, finalheight - height, scroll_duration); // 触发computescroll invalidate(); } /** * 开启上啦 */ private void startloadmore() { mpullloading = true; mfooterview.setvisibility(visible); if (onrefreshlistener != null) { tag=load; onrefreshlistener.onloadmore(); } } @override public void computescroll() { if (mscroller.computescrolloffset()) { if (mscrollback == scrollback_header) { mheaderview.setvisiableheight(mscroller.getcurry()); } postinvalidate(); invokeonscrolling(); } super.computescroll(); } @override public void setonscrolllistener(onscrolllistener l) { mscrolllistener = l; } @override public void onscrollstatechanged(abslistview view, int scrollstate) { if (mscrolllistener != null) { mscrolllistener.onscrollstatechanged(view, scrollstate); } } /** * 滑动监听 * @param view * @param firstvisibleitem * @param visibleitemcount * @param totalitemcount */ @override public void onscroll(abslistview view, int firstvisibleitem, int visibleitemcount, int totalitemcount) { mtotalitemcount = totalitemcount; if (mscrolllistener != null) { mscrolllistener.onscroll(view, firstvisibleitem, visibleitemcount, totalitemcount); } if(firstvisibleitem+visibleitemcount>=totalitemcount){ isfootervisible=true; }else{ isfootervisible=false; } } public void setonrefreshlistener(onrefreshlistener l) { onrefreshlistener = l; } /** * you can listen listview.onscrolllistener or this one. it will invoke * onxscrolling when header/footer scroll back. */ public interface onxscrolllistener extends onscrolllistener { public void onxscrolling(view view); } /** * implements this interface to get refresh/load more event. */ public interface onrefreshlistener { public void onrefresh(); public void onloadmore(); } /** * 上拉加载和下拉刷新请求完毕 */ public void complete(){ stoploadmore(); stoprefresh(); if(refresh.equals(tag)){ refreshtime.setrefreshtime(getcontext(),new date()); } } /** * 设置listview的模式,上拉和下拉 * @param mode */ public void setlistviewmode(int mode){ if(mode==both){ setpullrefreshenable(true); setpullloadenable(true); }else if(mode==footer){ setpullloadenable(true); }else if(mode==header){ setpullrefreshenable(true); } } /** * 判断是否可以上蜡加载 * @return */ private boolean canloadmore() { return isbottom() && !mpullloading && ispullingup(); } /** * 判断是否到达底部 * @return */ private boolean isbottom() { if (getcount() > 0) { if (getlastvisibleposition() == getadapter().getcount() - 1 && getchildat(getchildcount() - 1).getbottom() <= getheight()) { return true; } } return false; } private boolean ispullingup() { return (firsttouchy - lasttouchy) >= 200; } private void loaddata() { if (onrefreshlistener != null) { setloading(true); } } /** * 设置是否上拉 * @param loading */ public void setloading(boolean loading) { if (this == null) return; mpullloading = loading; if (loading) { mfooterview.setvisibility(visible); setselection(getadapter().getcount() - 1); onrefreshlistener.onloadmore(); } else { mfooterview.setvisibility(gone); firsttouchy = 0; lasttouchy = 0; } }
定义完了之后我们是这样用的:
rsmlv.setadapter(adapter); rsmlv.setlistviewmode(refreshswipemenulistview.header); rsmlv.setonrefreshlistener(this); swipemenucreator creator = new swipemenucreator() { @override public void create(swipemenu menu) { // 创建滑动选项 swipemenuitem rejectitem = new swipemenuitem( getapplicationcontext()); // 设置选项背景 rejectitem.setbackground(new colordrawable(getresources().getcolor(r.color.top))); // 设置选项宽度 rejectitem.setwidth(dp2px(80,getapplicationcontext())); // 设置选项标题 rejectitem.settitle("置顶"); // 设置选项标题 rejectitem.settitlesize(16); // 设置选项标题颜色 rejectitem.settitlecolor(color.white); // 添加选项 menu.addmenuitem(rejectitem); // 创建删除选项 swipemenuitem argeeitem = new swipemenuitem(getapplicationcontext()); argeeitem.setbackground(new colordrawable(getresources().getcolor(r.color.del))); argeeitem.setwidth(dp2px(80, getapplicationcontext())); argeeitem.settitle("删除"); argeeitem.settitlesize(16); argeeitem.settitlecolor(color.white); menu.addmenuitem(argeeitem); } }; rsmlv.setmenucreator(creator); rsmlv.setonmenuitemclicklistener(new refreshswipemenulistview.onmenuitemclicklistener() { @override public void onmenuitemclick(int position, swipemenu menu, int index) { switch (index) { case 0: //第一个选项 toast.maketext(mainactivity.this,"您点击的是置顶",toast.length_short).show(); break; case 1: //第二个选项 del(position,rsmlv.getchildat(position+1-rsmlv.getfirstvisibleposition())); break; } } });
为了和qq有着一样的体验效果,小编加了一个删除item的动画
看起来就不会太生硬了,用户体验也比较好:
/** * 删除item动画 * @param index * @param v */ private void del(final int index, view v){ final animation animation = (animation) animationutils.loadanimation(v.getcontext(), r.anim.list_anim); animation.setanimationlistener(new animation.animationlistener() { public void onanimationstart(animation animation) {} public void onanimationrepeat(animation animation) {} public void onanimationend(animation animation) { data.remove(index); adapter.notifydatasetchanged(); animation.cancel(); } }); v.startanimation(animation); }
好了到这里了,我们的组合控件-上拉下拉+左滑删除的组合listview就定义好了,分享出来小伙伴们以后遇到可以直接拿来用,”到时候小船儿也不会再翻了”,不合理的地方希望大家提出来,共同交流,进步。
以上所述是小编给大家介绍的android自定义组合控件之自定义下拉刷新和左滑删除实例代码,希望对大家有所帮助!