Android自定义控件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图,于是就将这个状态图画出来了。

总结

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

(0)

相关推荐

  • 详解xamarin Android 实现ListView万能适配器

    详解xamarin Android 实现ListView万能适配器 早些时候接触xamarin Android 的列表,写了很多ListView的Adapter,建一个ListView就写一个Adapter,每一个Adapter里面还有去写一个ViewHolder的类来优化,自从看了hongyang博客的listview万能适配器的文章,学习良多,所以就写篇关于xamarin android ListView通用适配器的文章. 本章主要分为以下三点: 打造通用的ViewHolder优化ListV

  • ListView通用泛型适配器

    还记得我们之前说的ListView吗,(这个难用的控件-.+)我们在用他的同时也用到了一个叫做适配器Adapter的东西.一般我们用一个类继承BaseAdapter,来进行数据和控件的适配. 但是我们每一种适配器都只是为了适配一种数据源和一种布局,如果用到的少还好,如果要用到十几种,我们是不是要写十几个适配器呢?这个想法真的是太蠢了! 有一种适配器写法,可以做到一个适配器与多种类型数据和布局进行适配,这个东西叫做通用适配器(因为他是用到泛型实现的,我称他为泛型适配器),今天我们来看一下这种适配器

  • android使用flutter的ListView实现滚动列表的示例代码

    现如今打开一个 App,比如头条.微博,都会有长列表,随着我们不断地滑动,视窗内的内容也会不断地更新.今天就用 Flutter 实现一下这种效果. 这里的表现其实就相当于有一个固定长度的容器,然后超出的内容是不可见的,只有当你向上或向下滑动屏幕时,视窗外看不见的内容才会出现在视窗中.如果在 web 开发时,是需要容器加上样式 overflow: auto; 要想用 Flutter 实现,其实也是很简单的,因为 Flutter 为我们提供了 ListView 组件. ListView 主要有以下几

  • Android通过代码控制ListView上下滚动的方法

    本文将介绍一种通过代码控制ListView上下滚动的方法. 先上图: 按下按钮会触发ListView滚动或停止. 实现该功能并不难,下面给出主要代码MainActivity.java package cn.guet.levide; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View;

  • Android解决ScrollView下嵌套ListView和GridView中内容显示不全的问题

    最近为公司做的一个Demo里面用到了ScrollView嵌套了GridView和ListView,然而在嵌套的时候我发现GridView和ListView都是不能完全显示,显示的基本上都是单行的数据,最后查找资料和翻阅文档看到原因是ListView和GridView的绘制过程中在ScrollView中无法准确的测量自身的高度,而且listVIew和GridView抢占了焦点,使得ListView和GrideView具有自身的显示的效果,这样就测量出显示一行条目即可的距离,其他的条目根据自身的滑动

  • Android ListView适配器(Adapter)优化方法详解

    Android ListView的优化,在做Android项目的时候,在用到ListView 界面及数据显示,这个时候如果资源过大,对项目来说,用户体验肯定是不好的,这里就对如何优化做了详细介绍: Adapter的作用就是ListView界面与数据之间的桥梁,当列表里的每一项显示到页面时,都会调用Adapter的getView方法返回一个View.想过没有? 在我们的列表有1000000项时会是什么样的?是不是会占用极大的系统资源? ListView的Adapter的作用如下图所示: 先看看下面

  • Android ListView和Adapter数据适配器的简单介绍

    ListView 显示大量相同格式数据 常用属性: listSelector listView每项在选中.按下等不同状态时的Drawable divider ListView每项间的间隔Drawable dividerHeight ListView每项间间隔的间隔高度 常用方法: setAdapter() 设置数据适配器 setOnItemClickListener() 设置每项点击事件监听 addHeaderView() 添加头视图 addFooterView() 添加脚视图 setEmpty

  • Android巧用XListView实现万能下拉刷新控件

    摘要:想必大家做开发的时候都会用到下拉刷新的控件,现在各种第三方的下拉刷新控件不胜枚举.当然最NB的还是XListView.其他也有针对GridView,ScrollView,LinearLayout进行重写的下拉刷新控件.本文针对xListView采取一种巧用办法,可以实现各种控件的下拉刷新. 这种巧用思路有人可能已经想到,因为ListView本身就有addHeaderView方法,用该方法我们可以添加任何布局的View.因此本文的思路就是往xListView的头部添加我们自定义写的布局文件.

  • MVPXlistView展示上拉下拉效果

    本文实例为大家分享了MVPXlistView上拉下拉展示的具体代码,供大家参考,具体内容如下 抽基类 package com.gs.gg.day8.back; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; public abstract class BackActivity extends AppCompa

  • Android ListView万能适配器实例代码

    ListView是开发中最常用的控件了,但是总是会写重复的代码,浪费时间又没有意义. 最近参考一些资料,发现一个万能ListView适配器,代码量少,节省时间,总结一下分享给大家. 首先有一个自定义的Adapter继承于BaseAdapter,下面是自定义的Adapter,精华在getView()方法中 package com.example.mylistview.util; import java.util.List; import android.content.Context; impor

随机推荐