Android自定义控件实现下拉刷新效果

Android自定义控件实现下拉刷新效果,第1张

概述app开发中下拉刷新是最常接触到的一个功能,也有很多开源的框架,封装的非常棒。前段时间了解了一下ViewDragHelper,遂用它实现了下拉刷新的功能。

app开发中下拉刷新是最常接触到的一个功能,也有很多开源的框架,封装的非常棒。前段时间了解了一下VIEwDragHelper,遂用它实现了下拉刷新的功能。

大概和我之前的ViewDragHelper之拖动加载(类似淘宝)这篇代码类似。只是做了相关改动。具体的可以看一下那篇博文了解一下用到的VIEwDragHelper的一些知识点。该界面主要是一个linearLayout,上面的下拉刷新是一个textvIEw(用TV代替),当然这个可以定制,在此只是用一个textvIEw代替,实现简单的功能,下面是一个ListvIEw(用LV代替),当然ListvIEw也是可以定制的,可以使grIDvIEw或者其他你想要的都可以,在此也是只用ListvIEw代替。大概的讲讲吧:

首先,在onLayout中将TV置于屏幕上方,将LV充满屏幕;

上图中蓝色部分是整个手机的屏幕,红色部分是下拉提示TV。TV是置于屏幕之外的是不显示的。

@OverrIDe  protected voID onLayout(boolean changed,int l,int t,int r,int b) {   if (pullText.gettop() == 0) {    vIEwHeight = pullText.getMeasuredHeight();    pullText.layout(l,r,b);    myList.layout(l,b);    pullText.offsettopAndBottom(-vIEwHeight);   } else {    pullText.layout(l,pullText.gettop(),pullText.getBottom());    myList.layout(l,myList.gettop(),myList.getBottom());   }  } 

 上面的代码段中,pullText即是TV,myList是LV。这样在下拉LV的时候,TV就会跟着往下走,所以就会出现在屏幕中实现我们想要的效果。

 /**   * 这是拖拽效果的主要逻辑   */  private class DragHelperCallback extends VIEwDragHelper.Callback {    @OverrIDe   public voID onVIEwpositionChanged(VIEw changedVIEw,int left,int top,int dx,int dy) {    int childindex = 1;    if (changedVIEw == myList) {     childindex = 2;    }    onVIEwPosChanged(childindex,top);   }    @OverrIDe   public boolean tryCaptureVIEw(VIEw child,int pointerID) {    return true;   }    @OverrIDe   public int getVIEwVerticalDragRange(VIEw child) {    return 1;   }    @OverrIDe   public voID onVIEwReleased(VIEw releasedChild,float xvel,float yvel) {    refreshOrNot(releasedChild,yvel);   }    @OverrIDe   public int clampVIEwpositionVertical(VIEw child,int dy) {    int finaltop = top;    if (child == pullText) {     if (top > 0) {      finaltop = 0;     }    } else if (child == myList) {     if (top < 0) {      finaltop = 0;     }     if(top >= vIEwHeight){      pullText.setText("松开刷新");     }else{      pullText.setText("下拉刷新");     }    }    return child.gettop() + (finaltop - child.gettop()) / 2;   }  }

上面的代码段中,主要是在clampVIEwpositionVertical中判断滑动的位置,作用的子vIEw。其他就不多说了,大致和之前的博客相同。主要说说onVIEwReleased吧。在此函数中是在用户手势抬起时响应的,所以我们在此实现下拉后的刷新。我们先定义一个接口,以便在刷新的时候调用。

public interface pulltorefreshNotifIEr {   public voID onPull();  } 
public voID setpulltorefreshNotifIEr(pulltorefreshNotifIEr pullNotifIEr) {   this.pullNotifIEr = pullNotifIEr;  } 
private voID refreshOrNot(VIEw releasedChild,float yvel) {   int finaltop = 0;   if (releasedChild == pullText) {    // 拖动第一个vIEw松手    if (yvel < -50) {     finaltop = 0;    } else {     finaltop = vIEwHeight;    }   } else {    // 拖动第二个vIEw松手    if (yvel > vIEwHeight - 5 || releasedChild.gettop() >= vIEwHeight) {     finaltop = vIEwHeight;     if (null != pullNotifIEr) {      pullNotifIEr.onPull();     }     pullText.setText("正在刷新");    }   }    if (VDH.smoothSlIDeVIEwTo(myList,finaltop)) {    VIEwCompat.postInvalIDateOnAnimation(this);   }  } 

拖动第二个vIEw时,也就是LV时,我们判断一下是否需要刷新,需要刷新则执行onPull();
然后我们来看一下主要的Activity:

package com.maxi.pulltorefreshtest;  import androID.annotation.Suppresslint; import androID.app.Activity; import androID.os.Bundle; import androID.os.Handler; import androID.os.Message;  import com.maxi.pulltorefreshtest.adapter.ProjectAdapter; import com.maxi.pulltorefreshtest.Widget.MyListVIEw; import com.maxi.pulltorefreshtest.Widget.PullToRefreshGroup; import com.maxi.pulltorefreshtest.Widget.PullToRefreshGroup.pulltorefreshNotifIEr;  public class MainActivity extends Activity {  private PullToRefreshGroup pullListgroup;  private boolean isDown = false;  private MyListVIEw myList;  private ProjectAdapter pa;  @OverrIDe  protected voID onCreate(Bundle savedInstanceState) {   super.onCreate(savedInstanceState);   setContentVIEw(R.layout.activity_main);   findVIEw();   init();  }   private voID findVIEw() {   pullListgroup = (PullToRefreshGroup) findVIEwByID(R.ID.pulltorefresh);   myList = pullListgroup.returnMyList();  }   private voID init() {   pulltorefreshNotifIEr pullNotifIEr = new pulltorefreshNotifIEr() {    @OverrIDe    public voID onPull() {     // Todo auto-generated method stub     downLoad();    }   };   pullListgroup.setpulltorefreshNotifIEr(pullNotifIEr);   pa = new ProjectAdapter(this);   myList.setAdapter(pa);   pa.notifyDataSetChanged();  }   private voID downLoad() {   if (!isDown) {    isDown = true;    new Thread(new Runnable() {      @OverrIDe     public voID run() {      // Todo auto-generated method stub      try {       Thread.sleep(2000);       handler.sendEmptyMessage(1);      } catch (InterruptedException e) { //      Todo auto-generated catch block       e.printstacktrace();      }     }    }).start();   }  }   @Suppresslint("HandlerLeak")  private Handler handler = new Handler() {    @OverrIDe   public voID handleMessage(Message msg) {    // Todo auto-generated method stub    super.handleMessage(msg);    switch (msg.what) {    case 1:     pullListgroup.refreshComplete();     isDown = false;     break;    default:     break;    }   }   }; } 

我们在他刷新的时候执行downLoad();刷新数据。为了达到效果可以看出我让线程暂停2s。然后调用refreshComplete();

public voID refreshComplete() {  if (VDH.smoothSlIDeVIEwTo(myList,0)) {   VIEwCompat.postInvalIDateOnAnimation(this);  } } 

实现刷新好后让TV继续返回屏幕上方。

上段代码中我们发现MyListVIEw是重写的ListVIEw,主要是处理手势事件的。

package com.maxi.pulltorefreshtest.Widget;  import androID.content.Context; import androID.util.AttributeSet; import androID.vIEw.MotionEvent; import androID.vIEw.VIEw; import androID.Widget.ListVIEw;  public class MyListVIEw extends ListVIEw {  boolean allowDragBottom = true;  float downY = 0;  boolean needConsumetouch = true;  public MyListVIEw(Context context){   super(context);  }  public MyListVIEw(Context context,AttributeSet attrs) {   super(context,attrs);   // Todo auto-generated constructor stub  }   @OverrIDe  public boolean dispatchtouchEvent(MotionEvent ev) {   if (ev.getAction() == MotionEvent.ACTION_DOWN) {    downY = ev.getRawY();    needConsumetouch = true;    if (getMyScrollY() == 0) {     allowDragBottom = true;    } else {     allowDragBottom = false;    }   } else if (ev.getAction() == MotionEvent.ACTION_MOVE) {    if (!needConsumetouch) {     getParent().requestdisallowIntercepttouchEvent(false);     return false;    } else if (allowDragBottom) {     if (downY - ev.getRawY() < -2) {      needConsumetouch = false;      getParent().requestdisallowIntercepttouchEvent(false);      return false;     }    }   }   getParent().requestdisallowIntercepttouchEvent(needConsumetouch);   return super.dispatchtouchEvent(ev);  }   public int getMyScrollY() {   VIEw c = getChildAt(0);   if (c == null) {    return 0;   }   int firstVisibleposition = getFirstVisibleposition();   int top = c.gettop();   return -top + firstVisibleposition * c.getHeight();  } } 

ok。先这样吧。像上拉加载更多,我感觉也可以这么实现。有时间试试吧,大家有时间也可以动动手试试。

好吧。大致就这些,有疑问或建议请留言,共同进步,谢谢!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。

总结

以上是内存溢出为你收集整理的Android自定义控件实现下拉刷新效果全部内容,希望文章能够帮你解决Android自定义控件实现下拉刷新效果所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1144831.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存