Android自定义控件ListView下拉刷新的代码

小编 2026-07-09 阅读:604 评论:0
ListView在实际实用中,一般都会有下新刷新和上拉加载的动态效果,今天要学的就是如何自定义带下拉刷新的ListView。 原理解析:一般将有下拉刷新的listview分成四种不同的状态来进行不同的显示效果。...

ListView在实际实用中,一般都会有下新刷新和上拉加载的动态效果,今天要学的就是如何自定义带下拉刷新的ListView。

原理解析:一般将有下拉刷新的listview分成四种不同的状态来进行不同的显示效果。

  • 1.完成状态done:listview正常显示状态
  • 2.下拉状态pull:listview正在下拉时的状态
  • 3.释放状态release:listview下拉后松开的状态
  • 4.更新状态refreshing:listview下拉后加载数据时的状态

实现步骤:

  • 自定义CustomListView继承自ListView,添加headerView,里面的布局是有下拉刷新的文字与图片
  • 为listview创建适配器,随便弄一些数据做一些数据源放入到listview的适配器中,好测试显示。
  • 自定义的带有头部的ListView首先要将头部视图隐藏掉,添加头视图的代码是listview.addHeaderView()。
  • 注意:这里并不能用headerView对象的setVisibility()来实现隐藏的效果,当你调用这个添加头部视图的方法时,头部位置不管有没有视图都会占据一个位置。所以得用setPadding()的TOP为负数来实现这个功能。
  • 具体代码实现
package com.hapzhu.customlv;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
public class CustomListview extends ListView {
  View headerView;
  int height;
  private TextView tvActionTip;
  private ImageView ivArrow;
  private ProgressBar pbRefreshing;
  final static int STATE_DONE = 1;
  final static int STATE_PULL = 2;
  final static int STATE_RELEASE = 3;
  final static int STATE_REFRESHING = 4;
  int currentState;
  int downY;
  public CustomListview(Context context, AttributeSet attrs) {
    super(context, attrs);
    headerView = View.inflate(context, R.layout.listview_header, null);
    this.addHeaderView(headerView);
    // 用setPadding方法设置Top的大小来把headerview隐藏掉
    // 不能用GetHeight方法来实现,因为这个方法只能用来测试可见的控件
    // 要用measureHeight的方法来实现测试,这个方法要先测试0,0的位置
    headerView.measure(0, 0);
    height = headerView.getMeasuredHeight();
    headerView.setPadding(0, -height, 0, 0);
    initView();
    // 设置第一个状态
    currentState = STATE_DONE;
  }
  private void initView() {
    tvActionTip = (TextView) headerView.findViewById(R.id.tv_state);
    ivArrow = (ImageView) headerView.findViewById(R.id.iv_arrow);
    pbRefreshing = (ProgressBar) headerView.findViewById(R.id.progressBar);
  }
  boolean isRefresh = false;
  @Override
  public boolean onTouchEvent(MotionEvent ev) {
    try {
      // 事件类型
      int action = ev.getAction();
      switch (action) {
      case MotionEvent.ACTION_DOWN:// 往下滑的手势
        if (currentState == STATE_DONE) {// 只有在完成状态时才会有业务动作
          // 触发下拉手势的Y坐标
          downY = (int) ev.getY();
          // 切换状态
          currentState = STATE_PULL;
        }
        break;
      case MotionEvent.ACTION_MOVE:// 正在拖动的手势
        if (currentState == STATE_PULL) {// 只有在下拉状态时才会有动作
          int currentY = (int) ev.getY();// 得到正在不断改变的当前Y坐标
          int top = currentY - downY - height;// 这个值是下拉时头部视图的高度显示,要慢慢变化
          headerView.setPadding(0, top, 0, 0);
          if (currentY - downY > height) {// 如果下拉的高度超过了头视图的高度,则改变状态
            currentState = STATE_RELEASE;
            tvActionTip.setText(\"松开刷新\");
          }
        }
        break;
      case MotionEvent.ACTION_UP:
        if (currentState == STATE_RELEASE) {// 只有在释放状态时才进行刷新动作
          tvActionTip.setText(\"刷新中\");// 改变文字 提示
          currentState = STATE_REFRESHING;// 改变状态,变为刷新状态
          ivArrow.setVisibility(GONE);// 箭头隐藏
          pbRefreshing.setVisibility(VISIBLE);// 进度条显示
          isRefresh = true;
          if(onRefreshListener!=null){
            //如果回调接口不为空,则进行更新的事务
            onRefreshListener.OnRefresh(this);
          }
        } else {
          if (!isRefresh) {
            // 如果当前的下拉距离小于高度时,再把头部视图隐藏
            headerView.setPadding(0, -height, 0, 0);
            // 一定要记得把状态改回去,不然会没法再次向下拉
            currentState = STATE_DONE;
          }
        }
        break;
      }
    } catch (Exception e) {
    }
    return super.onTouchEvent(ev);
  }
  // 1定义接口
  interface OnRefreshListener {
    // 在主程序中使用框架中的Custom来改变数据更新完之后的界面
    public void OnRefresh(CustomListview customLv);
  }
  // 2.申明接口
  OnRefreshListener onRefreshListener;
  // 3.传递接口
  public void setOnRefreshListener(OnRefreshListener onRefreshListener) {
    this.onRefreshListener = onRefreshListener;
  }
  public void refreshComplete(){
    isRefresh=false;
    //更新数据结果后,再回调这个方法
    headerView.setPadding(0, -height, 0, 0);
    // 一定要记得把状态改回去,不然会没法再次向下拉
    currentState = STATE_DONE;
    //将进度条设为不可见,将箭头设为可见,将文字改回去
    ivArrow.setVisibility(VISIBLE);// 箭头显示
    pbRefreshing.setVisibility(GONE);// 进度条隐去
    tvActionTip.setText(\"下拉刷新\");// 改变文字 提示
  }
}

今天新学了UML图,于是就将这个状态图画出来了。

\"\"

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。如果你想了解更多相关内容请查看下面相关链接

版权声明

本文仅代表作者观点,不代表百度立场。
本文系作者授权百度百家发表,未经许可,不得转载。

热门文章
  • Sequential Monte Carlo Methods (SMC) 序列蒙特卡洛/粒子滤波/Bootstrap Filtering

    Sequential Monte Carlo Methods (SMC) 序列蒙特卡洛/粒子滤波/Bootstrap Filtering
    Problem Statement 我们考虑一个具有马尔可夫性质、非线性、非高斯的状态空间模型(State Space Model):对于一个时间序列上的观测结果{yt,t∈N}\\{ y_t , t \\in N \\}{yt​,t∈N},我们认为每个观测结果yty_tyt​的生成依赖于一个无法直接观察的隐变量xt∈{xt,t∈N}x_t \\in \\{x_t , t \\in N \\}xt​∈{xt​,t∈N},即:p(...
  • 机房智能化温湿度解决方式之POE供电以太网温湿度传感器

    机房智能化温湿度解决方式之POE供电以太网温湿度传感器
    机房智能化温湿度解决方式之POE供电以太网温湿度传感器 北京盈创力和电子科技有限公司 智能型TCP网口温湿度记录仪 北京IP网络温湿度记录仪厂家,北京盈创力和 北京智能型TCP网口温湿度记录仪IP网络温湿度记录仪是一种新型的基于TCP/IP协议双绞线以太网标准温湿度采集模块,利用它可以实现现场温度值、相对湿度值的采集,同时利用其自身的RJ45通信接口可以方便地和机房监控主机或交换机集线器进行联网。 工作于-40℃~85℃工业级带...
  • Hive 系统函数及示例

    Hive 系统函数及示例
    查看所有系统函数 show functions; 函数分类 内置函数【系统函数】 数学函数: floor、round、ceil、cos、log2等 字符串函数: length、reverse、trim、lower、get_json_object、repeat等 收集函数: size 转换函数: cast 日期函数: year、month、datediff、date、date_add等 条件函数: coalesce、case…w...
  • CSRF的原理和防范措施

    CSRF的原理和防范措施
    a)攻击原理:i.用户C访问正常网站A时进行登录,浏览器保存A的cookieii.用户C再访问攻击网站B,网站B上有某个隐藏的链接或者图片标签会自动请求网站A的URL地址,例如表单提交,传指定的参数iii.而攻击网站B在访问网站A的时候,浏览器会自动带上网站A的cookieiv.所以网站A在接收到请求之后可判断当前用户是登录状态,所以...
  • HTTP状态保持的原理

    HTTP状态保持的原理
    a)在用户登录之后,浏览器返回响应的时候会在响应中添加上cookieb)浏览器接收到cookie之后会自动保存c)当用户再次请求同一服务器中的其他网页的时候,浏览器会自动带上之前保存的cookied)服务接收到请求之后可以请 request 对象中取到cookie 判断当前用户是否登录  Http是无状态的,就是连接时数据互通,关闭后...
标签列表