当前位置: 移动技术网 > IT编程>移动开发>Android > Android中ListView下拉刷新的实现代码

Android中ListView下拉刷新的实现代码

2019年07月24日  | 移动技术网IT编程  | 我要评论

购物 网站,浙江毅腾,福建东南汽车

android中listview下拉刷新

实现效果图:

listview中的下拉刷新是非常常见的,也是经常使用的,看到有很多同学想要,那我就整理一下,供大家参考。那我就不解释,直接上代码了。

这里需要自己重写一下listview,重写代码如下:

package net.loonggg.listview; 
 
import java.util.date; 
 
import android.content.context; 
import android.util.attributeset; 
import android.view.layoutinflater; 
import android.view.motionevent; 
import android.view.view; 
import android.view.viewgroup; 
import android.view.animation.linearinterpolator; 
import android.view.animation.rotateanimation; 
import android.widget.abslistview; 
import android.widget.abslistview.onscrolllistener; 
import android.widget.imageview; 
import android.widget.linearlayout; 
import android.widget.listview; 
import android.widget.progressbar; 
import android.widget.textview; 
 
public class mylistview extends listview implements onscrolllistener { 
 
  private final static int release_to_refresh = 0;// 下拉过程的状态值 
  private final static int pull_to_refresh = 1; // 从下拉返回到不刷新的状态值 
  private final static int refreshing = 2;// 正在刷新的状态值 
  private final static int done = 3; 
  private final static int loading = 4; 
 
  // 实际的padding的距离与界面上偏移距离的比例 
  private final static int ratio = 3; 
  private layoutinflater inflater; 
 
  // listview头部下拉刷新的布局 
  private linearlayout headerview; 
  private textview lvheadertipstv; 
  private textview lvheaderlastupdatedtv; 
  private imageview lvheaderarrowiv; 
  private progressbar lvheaderprogressbar; 
 
  // 定义头部下拉刷新的布局的高度 
  private int headercontentheight; 
 
  private rotateanimation animation; 
  private rotateanimation reverseanimation; 
 
  private int starty; 
  private int state; 
  private boolean isback; 
 
  // 用于保证starty的值在一个完整的touch事件中只被记录一次 
  private boolean isrecored; 
 
  private onrefreshlistener refreshlistener; 
 
  private boolean isrefreshable; 
 
  public mylistview(context context) { 
    super(context); 
    init(context); 
  } 
 
  public mylistview(context context, attributeset attrs) { 
    super(context, attrs); 
    init(context); 
  } 
 
  private void init(context context) { 
    setcachecolorhint(context.getresources().getcolor(r.color.transparent)); 
    inflater = layoutinflater.from(context); 
    headerview = (linearlayout) inflater.inflate(r.layout.lv_header, null); 
    lvheadertipstv = (textview) headerview 
        .findviewbyid(r.id.lvheadertipstv); 
    lvheaderlastupdatedtv = (textview) headerview 
        .findviewbyid(r.id.lvheaderlastupdatedtv); 
 
    lvheaderarrowiv = (imageview) headerview 
        .findviewbyid(r.id.lvheaderarrowiv); 
    // 设置下拉刷新图标的最小高度和宽度 
    lvheaderarrowiv.setminimumwidth(70); 
    lvheaderarrowiv.setminimumheight(50); 
 
    lvheaderprogressbar = (progressbar) headerview 
        .findviewbyid(r.id.lvheaderprogressbar); 
    measureview(headerview); 
    headercontentheight = headerview.getmeasuredheight(); 
    // 设置内边距,正好距离顶部为一个负的整个布局的高度,正好把头部隐藏 
    headerview.setpadding(0, -1 * headercontentheight, 0, 0); 
    // 重绘一下 
    headerview.invalidate(); 
    // 将下拉刷新的布局加入listview的顶部 
    addheaderview(headerview, null, false); 
    // 设置滚动监听事件 
    setonscrolllistener(this); 
 
    // 设置旋转动画事件 
    animation = new rotateanimation(0, -180, 
        rotateanimation.relative_to_self, 0.5f, 
        rotateanimation.relative_to_self, 0.5f); 
    animation.setinterpolator(new linearinterpolator()); 
    animation.setduration(250); 
    animation.setfillafter(true); 
 
    reverseanimation = new rotateanimation(-180, 0, 
        rotateanimation.relative_to_self, 0.5f, 
        rotateanimation.relative_to_self, 0.5f); 
    reverseanimation.setinterpolator(new linearinterpolator()); 
    reverseanimation.setduration(200); 
    reverseanimation.setfillafter(true); 
 
    // 一开始的状态就是下拉刷新完的状态,所以为done 
    state = done; 
    // 是否正在刷新 
    isrefreshable = false; 
  } 
 
  @override 
  public void onscrollstatechanged(abslistview view, int scrollstate) { 
 
  } 
 
  @override 
  public void onscroll(abslistview view, int firstvisibleitem, 
      int visibleitemcount, int totalitemcount) { 
        if (firstvisibleitem == 0) { 
          isrefreshable = true; 
         } else { 
          isrefreshable = false; 
         }   
    } 
 
  @override 
  public boolean ontouchevent(motionevent ev) { 
    if (isrefreshable) { 
      switch (ev.getaction()) { 
      case motionevent.action_down: 
        if (!isrecored) { 
          isrecored = true; 
          starty = (int) ev.gety();// 手指按下时记录当前位置 
        } 
        break; 
      case motionevent.action_up: 
        if (state != refreshing && state != loading) { 
          if (state == pull_to_refresh) { 
            state = done; 
            changeheaderviewbystate(); 
          } 
          if (state == release_to_refresh) { 
            state = refreshing; 
            changeheaderviewbystate(); 
            onlvrefresh(); 
          } 
        } 
        isrecored = false; 
        isback = false; 
 
        break; 
 
      case motionevent.action_move: 
        int tempy = (int) ev.gety(); 
        if (!isrecored) { 
          isrecored = true; 
          starty = tempy; 
        } 
        if (state != refreshing && isrecored && state != loading) { 
          // 保证在设置padding的过程中,当前的位置一直是在head,否则如果当列表超出屏幕的话,当在上推的时候,列表会同时进行滚动 
          // 可以松手去刷新了 
          if (state == release_to_refresh) { 
            setselection(0); 
            // 往上推了,推到了屏幕足够掩盖head的程度,但是还没有推到全部掩盖的地步 
            if (((tempy - starty) / ratio < headercontentheight)// 由松开刷新状态转变到下拉刷新状态 
                && (tempy - starty) > 0) { 
              state = pull_to_refresh; 
              changeheaderviewbystate(); 
            } 
            // 一下子推到顶了 
            else if (tempy - starty <= 0) {// 由松开刷新状态转变到done状态 
              state = done; 
              changeheaderviewbystate(); 
            } 
          } 
          // 还没有到达显示松开刷新的时候,done或者是pull_to_refresh状态 
          if (state == pull_to_refresh) { 
            setselection(0); 
            // 下拉到可以进入release_to_refresh的状态 
            if ((tempy - starty) / ratio >= headercontentheight) {// 由done或者下拉刷新状态转变到松开刷新 
              state = release_to_refresh; 
              isback = true; 
              changeheaderviewbystate(); 
            } 
            // 上推到顶了 
            else if (tempy - starty <= 0) {// 由done或者下拉刷新状态转变到done状态 
              state = done; 
              changeheaderviewbystate(); 
            } 
          } 
          // done状态下 
          if (state == done) { 
            if (tempy - starty > 0) { 
              state = pull_to_refresh; 
              changeheaderviewbystate(); 
            } 
          } 
          // 更新headview的size 
          if (state == pull_to_refresh) { 
            headerview.setpadding(0, -1 * headercontentheight 
                + (tempy - starty) / ratio, 0, 0); 
 
          } 
          // 更新headview的paddingtop 
          if (state == release_to_refresh) { 
            headerview.setpadding(0, (tempy - starty) / ratio 
                - headercontentheight, 0, 0); 
          } 
 
        } 
        break; 
 
      default: 
        break; 
      } 
    } 
    return super.ontouchevent(ev); 
  } 
 
  // 当状态改变时候,调用该方法,以更新界面 
  private void changeheaderviewbystate() { 
    switch (state) { 
    case release_to_refresh: 
      lvheaderarrowiv.setvisibility(view.visible); 
      lvheaderprogressbar.setvisibility(view.gone); 
      lvheadertipstv.setvisibility(view.visible); 
      lvheaderlastupdatedtv.setvisibility(view.visible); 
 
      lvheaderarrowiv.clearanimation();// 清除动画 
      lvheaderarrowiv.startanimation(animation);// 开始动画效果 
 
      lvheadertipstv.settext("松开刷新"); 
      break; 
    case pull_to_refresh: 
      lvheaderprogressbar.setvisibility(view.gone); 
      lvheadertipstv.setvisibility(view.visible); 
      lvheaderlastupdatedtv.setvisibility(view.visible); 
      lvheaderarrowiv.clearanimation(); 
      lvheaderarrowiv.setvisibility(view.visible); 
      // 是由release_to_refresh状态转变来的 
      if (isback) { 
        isback = false; 
        lvheaderarrowiv.clearanimation(); 
        lvheaderarrowiv.startanimation(reverseanimation); 
 
        lvheadertipstv.settext("下拉刷新"); 
      } else { 
        lvheadertipstv.settext("下拉刷新"); 
      } 
      break; 
 
    case refreshing: 
 
      headerview.setpadding(0, 0, 0, 0); 
 
      lvheaderprogressbar.setvisibility(view.visible); 
      lvheaderarrowiv.clearanimation(); 
      lvheaderarrowiv.setvisibility(view.gone); 
      lvheadertipstv.settext("正在刷新..."); 
      lvheaderlastupdatedtv.setvisibility(view.visible); 
      break; 
    case done: 
      headerview.setpadding(0, -1 * headercontentheight, 0, 0); 
 
      lvheaderprogressbar.setvisibility(view.gone); 
      lvheaderarrowiv.clearanimation(); 
      lvheaderarrowiv.setimageresource(r.drawable.arrow); 
      lvheadertipstv.settext("下拉刷新"); 
      lvheaderlastupdatedtv.setvisibility(view.visible); 
      break; 
    } 
  } 
 
  // 此方法直接照搬自网络上的一个下拉刷新的demo,此处是“估计”headview的width以及height 
  private void measureview(view child) { 
    viewgroup.layoutparams params = child.getlayoutparams(); 
    if (params == null) { 
      params = new viewgroup.layoutparams( 
          viewgroup.layoutparams.fill_parent, 
          viewgroup.layoutparams.wrap_content); 
    } 
    int childwidthspec = viewgroup.getchildmeasurespec(0, 0 + 0, 
        params.width); 
    int lpheight = params.height; 
    int childheightspec; 
    if (lpheight > 0) { 
      childheightspec = measurespec.makemeasurespec(lpheight, 
          measurespec.exactly); 
    } else { 
      childheightspec = measurespec.makemeasurespec(0, 
          measurespec.unspecified); 
    } 
    child.measure(childwidthspec, childheightspec); 
  } 
 
  public void setonrefreshlistener(onrefreshlistener refreshlistener) { 
    this.refreshlistener = refreshlistener; 
    isrefreshable = true; 
  } 
 
  public interface onrefreshlistener { 
    public void onrefresh(); 
  } 
 
  public void onrefreshcomplete() { 
    state = done; 
    lvheaderlastupdatedtv.settext("最近更新:" + new date().tolocalestring()); 
    changeheaderviewbystate(); 
  } 
 
  private void onlvrefresh() { 
    if (refreshlistener != null) { 
      refreshlistener.onrefresh(); 
    } 
  } 
 
  public void setadapter(lvadapter adapter) { 
    lvheaderlastupdatedtv.settext("最近更新:" + new date().tolocalestring()); 
    super.setadapter(adapter); 
  } 
 
} 

重写完listview之后,在布局文件中是这么使用的,头部下拉刷新的布局文件lv_header.xml代码如下:

<?xml version="1.0" encoding="utf-8"?> 
<!-- listview的头部 --> 
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" 
  android:layout_width="fill_parent" 
  android:layout_height="wrap_content" 
  android:background="#000000" > 
 
  <!-- 内容 --> 
 
  <relativelayout 
    android:id="@+id/head_contentlayout" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:paddingleft="30dp" > 
 
    <!-- 箭头图像、进度条 --> 
 
    <framelayout 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_alignparentleft="true" 
      android:layout_centervertical="true" > 
 
      <!-- 箭头 --> 
 
      <imageview 
        android:id="@+id/lvheaderarrowiv" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:layout_gravity="center" 
        android:src="@drawable/arrow" /> 
 
      <!-- 进度条 --> 
 
      <progressbar 
        android:id="@+id/lvheaderprogressbar" 
        style="?android:attr/progressbarstylesmall" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:layout_gravity="center" 
        android:visibility="gone" /> 
    </framelayout> 
 
    <!-- 提示、最近更新 --> 
 
    <linearlayout 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_centerhorizontal="true" 
      android:gravity="center_horizontal" 
      android:orientation="vertical" > 
 
      <!-- 提示 --> 
 
      <textview 
        android:id="@+id/lvheadertipstv" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:text="下拉刷新" 
        android:textcolor="@color/white" 
        android:textsize="20sp" /> 
 
      <!-- 最近更新 --> 
 
      <textview 
        android:id="@+id/lvheaderlastupdatedtv" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:text="上次更新" 
        android:textcolor="@color/gold" 
        android:textsize="10sp" /> 
    </linearlayout> 
  </relativelayout> 
 
</linearlayout> 

在main.xml中进行设置,代码如下:

<?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="fill_parent" 
  android:background="#000000" 
  android:orientation="vertical" > 
 
  <net.loonggg.listview.mylistview 
    android:id="@+id/lv" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" /> 
 
</linearlayout> 

然后就是在mainactivity中实现,代码如下:

package net.loonggg.listview; 
 
import java.util.arraylist; 
import java.util.list; 
 
import net.loonggg.listview.mylistview.onrefreshlistener; 
import android.app.activity; 
import android.os.asynctask; 
import android.os.bundle; 
import android.view.view; 
 
public class mainactivity extends activity { 
  private list<string> list; 
  private mylistview lv; 
  private lvadapter adapter; 
 
  @override 
  protected void oncreate(bundle savedinstancestate) { 
    super.oncreate(savedinstancestate); 
    setcontentview(r.layout.activity_main); 
    lv = (mylistview) findviewbyid(r.id.lv); 
    list = new arraylist<string>(); 
    list.add("loonggg"); 
    list.add("我们都是开发者"); 
    list.add("我们都是开发者"); 
    list.add("我们都是开发者"); 
    list.add("我们都是开发者"); 
    list.add("我们都是开发者"); 
    list.add("我们都是开发者"); 
    list.add("我们都是开发者"); 
    list.add("我们都是开发者"); 
    list.add("我们都是开发者"); 
    list.add("我们都是开发者"); 
    list.add("我们都是开发者"); 
    list.add("我们都是开发者"); 
    list.add("我们都是开发者"); 
    list.add("我们都是开发者"); 
    list.add("我们都是开发者"); 
    list.add("我们都是开发者"); 
    adapter = new lvadapter(list, this); 
    lv.setadapter(adapter); 
 
    lv.setonrefreshlistener(new onrefreshlistener() { 
 
      @override 
      public void onrefresh() { 
        new asynctask<void, void, void>() { 
          protected void doinbackground(void... params) { 
            try { 
              thread.sleep(1000); 
            } catch (exception e) { 
              e.printstacktrace(); 
            } 
            list.add("刷新后添加的内容"); 
            return null; 
          } 
 
          @override 
          protected void onpostexecute(void result) { 
            adapter.notifydatasetchanged(); 
            lv.onrefreshcomplete(); 
          } 
        }.execute(null, null, null); 
      } 
    }); 
  } 
} 

这里还需要为listview设置一下adapter,自定义的adapter如下:

package net.loonggg.listview; 
 
import java.util.list; 
 
import android.content.context; 
import android.view.view; 
import android.view.viewgroup; 
import android.widget.baseadapter; 
import android.widget.textview; 
 
public class lvadapter extends baseadapter { 
  private list<string> list; 
  private context context; 
 
  public lvadapter(list<string> list, context context) { 
    this.list = list; 
    this.context = context; 
  } 
 
  @override 
  public int getcount() { 
    return list.size(); 
  } 
 
  @override 
  public object getitem(int position) { 
    return list.get(position); 
  } 
 
  @override 
  public long getitemid(int position) { 
    return position; 
  } 
 
  @override 
  public view getview(int position, view convertview, viewgroup parent) { 
    textview tv = new textview(context.getapplicationcontext()); 
    tv.settext(list.get(position)); 
    return tv; 
  } 
 
} 

到这里就完了,代码中的解释非常详细,具体的我就不多说了,也不解释了,自己看看并研究吧!

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网