欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android自定义listview布局实现上拉加载下拉刷新功能

程序员文章站 2024-03-31 12:42:58
listview实现上拉加载以及下拉刷新的方式有很多。下面是我写的一种自定义的布局,复用性也比较的强。首先就是继承的listview的自定义view。  &nb...

listview实现上拉加载以及下拉刷新的方式有很多。下面是我写的一种自定义的布局,复用性也比较的强。首先就是继承的listview的自定义view。

     autolistview.java:

package com.example.mic.testdemo.view; 
import android.annotation.targetapi; 
import android.content.context; 
import android.os.build; 
import android.os.bundle; 
import android.util.attributeset; 
import android.util.log; 
import android.view.layoutinflater; 
import android.view.motionevent; 
import android.view.view; 
import android.view.viewgroup; 
import android.view.animation.animation; 
import android.view.animation.linearinterpolator; 
import android.view.animation.rotateanimation; 
import android.widget.abslistview; 
import android.widget.imageview; 
import android.widget.listview; 
import android.widget.progressbar; 
import android.widget.textview; 
import com.example.mic.testdemo.r; 
import java.text.simpledateformat; 
/** 
 * created by dflenovo on 2016/8/3. 
 */ 
public class autolistview extends listview implements abslistview.onscrolllistener { 
  public static final string footer = "footer"; 
  public static final string header = "header"; 
  private static final int pull = 1; 
  private static final int none = 0; 
  //  private static final int release = 2; 
  private static final int refreshing = 2; 
  private static final int space = 20; 
  private static final string tag = "autolistview"; 
  private rotateanimation downanimation; 
  private rotateanimation upanimation; 
  private context context; 
  private layoutinflater inflater; 
  private view footer; 
  private view header; 
  private int headercontentinitialheight; 
  private int headercontentheight; 
  private onrefreshlistener onrefreshlistener; 
  private boolean loadenable; 
  private onloadlistener onloadlistener; 
  private int firstvisibleitem; 
  private boolean isloadingmore = false; 
  private int starty; 
  private int state; 
  private imageview iv_pull; 
  private int footerviewheight; 
  private progressbar mprogressbar; 
  private textview tvstate; 
  private textview tvlastupdatetime; 
  private boolean isscrolltobottom; 
  public autolistview(context context) { 
    super(context); 
    initview(context); 
  } 
  public autolistview(context context, attributeset attrs) { 
    super(context, attrs); 
    initview(context); 
  } 
  public autolistview(context context, attributeset attrs, int defstyleattr) { 
    super(context, attrs, defstyleattr); 
    initview(context); 
  } 
  @targetapi(build.version_codes.lollipop) 
  public autolistview(context context, attributeset attrs, int defstyleattr, int defstyleres) { 
    super(context, attrs, defstyleattr, defstyleres); 
    initview(context); 
  } 
  private void initview(context context) { 
    initheaderview(); 
    initfooterview(); 
    this.setonscrolllistener(this); 
// 
  } 
  private void initheaderview() { 
    header = view.inflate(getcontext(), r.layout.pull_to_refresh_header, null); 
    iv_pull = (imageview) header 
        .findviewbyid(r.id.iv_pull); 
    mprogressbar = (progressbar) header 
        .findviewbyid(r.id.pb_listview_header); 
    tvstate = (textview) header 
        .findviewbyid(r.id.tv_listview_header_state); 
    tvlastupdatetime = (textview) header 
        .findviewbyid(r.id.tv_listview_header_last_update_time); 
    // 设置最后刷新时间 
    tvlastupdatetime.settext("最后刷新时间: " + getlastupdatetime()); 
    header.measure(0, 0); // 系统会帮我们测量出headerview的高度 
    headercontentheight = header.getmeasuredheight(); 
    header.setpadding(0, -headercontentheight, 0, 0); 
    this.addheaderview(header,header,true); // 向listview的顶部添加一个view对象 
    initanimation(); 
  } 
  private void initanimation() { 
    upanimation = new rotateanimation(0f, -180f, 
        animation.relative_to_self, 0.5f, animation.relative_to_self, 
        0.5f); 
    upanimation.setduration(500); 
    upanimation.setfillafter(true); // 动画结束后, 停留在结束的位置上 
    downanimation = new rotateanimation(-180f, -360f, 
        animation.relative_to_self, 0.5f, animation.relative_to_self, 
        0.5f); 
    downanimation.setduration(500); 
    downanimation.setfillafter(true); // 动画结束后, 停留在结束的位置上 
  } 
  private string getlastupdatetime() { 
    simpledateformat sdf = new simpledateformat("yyyy-mm-dd hh:mm:ss"); 
    return sdf.format(system.currenttimemillis()); 
  } 
  private void initfooterview() { 
    footer = view.inflate(getcontext(), r.layout.foot_view, null); 
    footer.measure(0, 0); 
    footerviewheight = footer.getmeasuredheight(); 
    footer.setpadding(0, -footerviewheight, 0, 0); 
    this.addfooterview(footer,footer,true); 
  } 
  private void measureview(view child) { 
    viewgroup.layoutparams p = child.getlayoutparams(); 
    if (p == null) { 
      p = new viewgroup.layoutparams(viewgroup.layoutparams.match_parent, 
          viewgroup.layoutparams.wrap_content); 
    } 
    int childwidthspec = viewgroup.getchildmeasurespec(0, 0 + 0, p.width); 
    int lpheight = p.height; 
    int childheightspec; 
    if (lpheight > 0) { 
      childheightspec = measurespec.makemeasurespec(lpheight, 
          measurespec.exactly);//得到的是size。 
    } else { 
      childheightspec = measurespec.makemeasurespec(0, 
          measurespec.unspecified);//得到的是子布局的实际大小。 
    } 
    child.measure(childwidthspec, childheightspec); 
  } 
  private void toppadding(int toppadding) { 
    header.setpadding(header.getpaddingleft(), toppadding, 
        header.getpaddingright(), header.getpaddingbottom()); 
    header.invalidate(); 
  } 
  @override 
  public void onscrollstatechanged(abslistview abslistview, int i) { 
    if (i == scroll_state_idle 
        || i == scroll_state_fling) { 
      // 判断当前是否已经到了底部 
      if (isscrolltobottom && !isloadingmore) { 
        isloadingmore = true; 
        // 当前到底部 
        log.i(tag, "加载更多数据"); 
        footer.setpadding(0, 0, 0, 0); 
        this.setselection(this.getcount()); 
        if (onloadlistener != null) { 
          onloadlistener.onload(); 
        } 
      } 
    } 
  } 
  @override 
  public void onscroll(abslistview abslistview, int i, int i1, int i2) { 
    this.firstvisibleitem = i; 
    if (getlastvisibleposition() == (i2 - 1)) { 
      isscrolltobottom = true; 
    } else { 
      isscrolltobottom = false; 
    } 
  } 
  @override 
  public boolean ontouchevent(motionevent ev) { 
    switch (ev.getaction()) { 
// 
      case motionevent.action_down: 
        starty = (int) ev.gety(); 
        break; 
      case motionevent.action_move: 
        int movey = (int) ev.gety(); 
        // 移动中的y - 按下的y = 间距. 
        int diff = (movey - starty) / 2; 
        // -头布局的高度 + 间距 = paddingtop 
        int paddingtop = -headercontentheight + diff; 
        // 如果: -头布局的高度 > paddingtop的值 执行super.ontouchevent(ev); 
        if (firstvisibleitem == 0 
            && -headercontentheight < paddingtop) { 
          if (paddingtop > 0 && state == none) { // 完全显示了. 
            log.i(tag, "松开刷新"); 
            state = pull; 
            refreshheaderviewbystate(); 
          } else if (paddingtop < 0 
              && state == pull) { // 没有显示完全 
            log.i(tag, "下拉刷新"); 
            state = none; 
            refreshheaderviewbystate(); 
          } 
          // 下拉头布局 
          header.setpadding(0, paddingtop, 0, 0); 
        } 
        break; 
      case motionevent.action_up: 
        // 判断当前的状态是松开刷新还是下拉刷新 
        if (state == pull) { 
          log.i(tag, "刷新数据."); 
          // 把头布局设置为完全显示状态 
          header.setpadding(0, 0, 0, 0); 
          // 进入到正在刷新中状态 
          state = refreshing; 
          refreshheaderviewbystate(); 
          if (onrefreshlistener != null) { 
            onrefreshlistener.onrefresh(); // 调用使用者的监听方法 
          } 
        } else if (state == none) { 
          // 隐藏头布局 
          header.setpadding(0, -headercontentheight, 0, 0); 
        } 
        break; 
      default: 
        break; 
    } 
    return super.ontouchevent(ev); 
  } 
// 
  private void refreshheaderviewbystate() { 
    switch (state) { 
// 
      case none: // 下拉刷新状态 
        tvstate.settext("下拉刷新"); 
        iv_pull.startanimation(downanimation); // 执行向下旋转 
        break; 
      case pull: // 松开刷新状态 
        tvstate.settext("松开刷新"); 
        iv_pull.startanimation(upanimation); // 执行向上旋转 
        break; 
      case refreshing: // 正在刷新中状态 
        iv_pull.clearanimation(); 
        iv_pull.setvisibility(view.gone); 
        mprogressbar.setvisibility(view.visible); 
        tvstate.settext("正在刷新中..."); 
        break; 
      default: 
        break; 
    } 
  } 
  public void hideheaderview() { 
    header.setpadding(0, -headercontentheight, 0, 0); 
    iv_pull.setvisibility(view.visible); 
    mprogressbar.setvisibility(view.gone); 
    tvstate.settext("下拉刷新"); 
    tvlastupdatetime.settext("最后刷新时间: " + getlastupdatetime()); 
    state = none; 
  } 
  public void hidefooterview() { 
    footer.setpadding(0, -footerviewheight, 0, 0); 
    isloadingmore = false; 
  } 
  public void setonrefreshlistener(onrefreshlistener onrefreshlistener) { 
    this.onrefreshlistener = onrefreshlistener; 
  } 
  public void setonloadlistener(onloadlistener onloadlistener) { 
    this.onloadlistener = onloadlistener; 
  } 
  public void onrefresh() { 
    if (onrefreshlistener != null) { 
      onrefreshlistener.onrefresh(); 
    } 
  } 
  public void onload() { 
    if (onloadlistener != null) { 
      onloadlistener.onload(); 
    } 
  } 
  public interface onrefreshlistener {//定义下拉刷新接口 
    public void onrefresh(); 
  } 
  public interface onloadlistener {//定义上拉加载更多 
    public void onload(); 
  } 
} 

        上面的代码就是实现的关键.下面是头布局以及脚布局:

foot_view.xml:

<?xml version="1.0" encoding="utf-8"?> 
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" 
  android:layout_width="match_parent" 
  android:layout_height="wrap_content"> 
  <textview 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="加载更多" 
    android:textsize="20dp" 
    android:padding="10dp" 
    android:layout_centerhorizontal="true"/> 
</relativelayout> 

pull_to_refresh_header.xml:

<?xml version="1.0" encoding="utf-8"?> 
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" 
  android:layout_width="wrap_content" 
  android:layout_height="wrap_content" 
  android:orientation="horizontal"> 
  <framelayout 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_margin="10dip" > 
    <imageview 
      android:id="@+id/iv_pull" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_gravity="center" 
      android:minwidth="30dip" 
      android:src="@mipmap/xlistview_arrow" /> 
    <progressbar 
      android:id="@+id/pb_listview_header" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_gravity="center" 
      android:visibility="gone" /> 
  </framelayout> 
  <linearlayout 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:layout_gravity="center_vertical" 
    android:gravity="center_horizontal" 
    android:orientation="vertical" > 
    <textview 
      android:id="@+id/tv_listview_header_state" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:text="下拉刷新" 
      android:textcolor="#ff0000" 
      android:textsize="18sp" /> 
    <textview 
      android:id="@+id/tv_listview_header_last_update_time" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_margintop="5dip" 
      android:text="最后刷新时间: 2014-10-10 12:56:12" 
      android:textcolor="@android:color/black" 
      android:textsize="14sp" /> 
  </linearlayout> 
</linearlayout> 

Android自定义listview布局实现上拉加载下拉刷新功能

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?> 
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" 
  xmlns:tools="http://schemas.android.com/tools" 
  android:id="@+id/activity_main" 
  android:layout_width="match_parent" 
  android:layout_height="match_parent" 
  android:paddingbottom="@dimen/activity_vertical_margin" 
  android:paddingleft="@dimen/activity_horizontal_margin" 
  android:paddingright="@dimen/activity_horizontal_margin"  android:paddingtop="@dimen/activity_vertical_margin" tools:context="com.example.mic.testdemo.mainactivity">       <com.example.mic.testdemo.view.autolistview 
        android:id="@+id/lv" 
        android:layout_width="match_parent" 
       android:layout_height="match_parent"> 
      </com.example.mic.testdemo.view.autolistview> 
</relativelayout> 

      上面所完成的步骤就是在listview上下加载不同的布局,上面也是要复用的代码,下面的代码就是怎么使用的代码了.

mainactivity.java:

public class mainactivity extends appcompatactivity implements autolistview.onloadlistener,autolistview.onrefreshlistener { 
  private textview textview; 
  private string result; 
  private autolistview listview; 
  private myadater adater; 
  @override 
  protected void oncreate(bundle savedinstancestate) { 
    super.oncreate(savedinstancestate); 
    setcontentview(r.layout.activity_main); 
    listview = (autolistview) findviewbyid(r.id.lv);} 
listview.setonrefreshlistener(mainactivity.this); 
listview.setonloadlistener(mainactivity.this); 
@override 
  public void onload() { 
  } 
  @override 
  public void onrefresh() {} 

下面就是实现,就是在你需要的地方设置监听,以及上面加载以及刷新需要的操作就可以了!

以上所述是小编给大家介绍的android自定义listview布局实现上拉加载下拉刷新功能,希望对大家有所帮助