效果图:

一 首先创建一个类,继承ListView,编写其构造方法

public class RefreshListView  extends ListView {public RefreshListView(Context context) {this(context, null);}public RefreshListView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public RefreshListView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}private void init() {}
}

二 在activity中使用我们的RefreshListView控件

向ListView中设置数据的过程与我们android中提供的ListView设置数据的方式一至,这里就不贴出代码块了

此时运行的效果图

可以看到与我们正常的ListView是一样的

三 向RefresListView中添加我们下拉刷新使用到的头布局

头布局中的显示,包括显示下拉状态的向下的指示箭头,包括指示正在加载中的圆形进度条,包括显示状态与时间的文本框

定义头布局文件

xlistview_footer.xml文件中

<pre name="code" class="html"><?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="wrap_content"android:gravity="bottom" ><RelativeLayoutandroid:id="@+id/xlistview_header_content"android:layout_width="fill_parent"android:layout_height="60dp" ><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:gravity="center"android:orientation="vertical"android:id="@+id/xlistview_header_text"><TextViewandroid:id="@+id/xlistview_header_hint_textview"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="下拉刷新" /><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="3dp" ><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="上次更新时间:"android:textSize="12sp" /><TextViewandroid:id="@+id/xlistview_header_time"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="12sp" /></LinearLayout></LinearLayout><ImageViewandroid:id="@+id/xlistview_header_arrow"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignLeft="@id/xlistview_header_text"android:layout_centerVertical="true"android:layout_marginLeft="-35dp"android:src="@drawable/xlistview_arrow" /><ProgressBarandroid:id="@+id/xlistview_header_progressbar"android:layout_width="30dp"android:layout_height="30dp"android:layout_alignLeft="@id/xlistview_header_text"android:layout_centerVertical="true"android:layout_marginLeft="-40dp"android:visibility="visible" /></RelativeLayout></LinearLayout>

将头布局文件添加给ListView

在RefresListView中

private void init(Context context) {View view = View.inflate(context,R.layout.xlistview_header,null);this.addHeaderView(view);}

四 隐藏我们添加的头布局

首先让系统去帮我们测量头布局的高度,测量好后,我们就可以设置头布局的显示位置

 private void init(Context context) {View view = View.inflate(context, R.layout.xlistview_header, null);view.measure(0, 0);final int measuredHeight = view.getMeasuredHeight();view.setPadding(0,-measuredHeight,0,0);this.addHeaderView(view);}

五 设置头布局与LisView的联动

使用我们的控件实现OnTouchListener接口,并复写onTouch方法

import android.view.View.OnTouchListener;
public class RefreshListView  extends ListView implements OnTouchListener {....@Overridepublic boolean onTouch(View v, MotionEvent event) {return true;}}

在onTouch方法中我们需要重新设置显示头布局,所以我们需要将部分变量修改为成员变量

private void init(Context context) {setOnTouchListener(this);//获取头布局mHeaderView = View.inflate(context, R.layout.xlistview_header, null);//进行测量mHeaderView.measure(0, 0);//获取头布局的高度mHeaderHeight = mHeaderView.getMeasuredHeight();//设置头布局显示mHeaderView.setPadding(0, -mHeaderHeight, 0, 0);//添加到ListView中this.addHeaderView(mHeaderView);}

在onTouch方法中进行设置显示随ListView的滑动而显示的头布局

@Overridepublic boolean onTouchEvent( MotionEvent event) {int downY = 0;switch ( event.getAction()) {case MotionEvent.ACTION_DOWN://获取按下时的Y轴的位置downY = (int)event.getY();break;case MotionEvent.ACTION_MOVE:int moveY = (int)event.getY();//计算在Y轴方向的滑动偏移量,int diffY = moveY - downY;//计算我们的头布局需要移动的距离int paddingTop = -mHeaderHeight +diffY;//设置显示头布局mHeaderView.setPadding(0,paddingTop,0,0);break;default:break;}return true;}

注:这里之所以使用使用的是-mHeaderHeight高度,是因为我们在上面设置的头布局的paddingTop的大小正好是头布局的高度,也就是说刚刚好将头布局显示在屏幕外侧

优化代码

 //设置显示头布局,当显示的条目为第一条的时候并且移动的距离大于0的时候再开时向下移动if(getFirstVisiblePosition()==0&&diffY>0){mHeaderView.setPadding(0,paddingTop,0,0);return  true;}

六 定义更新下拉刷新过程中的头布局显示变化

定义下拉至释放刷新的中的变量

  // 代表下拉刷新状态 private final int PULL_REFRESH_STATE = 0;// 释放刷新状态private final int RELEASE_STATE = 1; // 正在刷新状态private final int RELEASEING = 2; // 默认当前是下拉刷新状态private int header_current_state = PULL_REFRESH_STATE;

创建更新头布局的方法

//更新头布局的方法private void updateHeaderView() {switch (header_current_state) {case PULL_REFRESH_STATE:   //下拉刷新状态break;case RELEASE_STATE:        //释放刷新状态break;case RELEASEING:           //正在刷新的状态break;}}

在onTouchEvent方法 中ACTION_MOVE事件处理中调用使用我们的更新头布局的方法

case MotionEvent.ACTION_MOVE:int moveY = (int)event.getY();//计算在Y轴方向的滑动偏移量,int diffY = moveY - downY;//计算我们的头布局需要移动的距离int paddingTop = -mHeaderHeight +diffY;//设置显示头布局,当显示的条目为第一条的时候并且移动的距离大于0的时候再开时向下移动if(getFirstVisiblePosition()==0&&diffY>0){//判断paddingTop 来更新头布局if (paddingTop > 0 && header_current_state != RELEASE_STATE) {// System.out.println("进入释放刷新状态");header_current_state = RELEASE_STATE;// 更新头布局状态updateHeaderView();} else if (paddingTop < 0&& header_current_state != PULL_REFRESH_STATE) {// System.out.println("~~~~下拉刷新状态~~~~");header_current_state = PULL_REFRESH_STATE;updateHeaderView();}mHeaderView.setPadding(0,paddingTop,0,0);return  true;}

然后我们在方法updateHeaderView这个方法中对应的状态下更新设置显示我们头布局中的信息

 //显示下拉上拉正在刷新状态的textviewmXlistviewHeaderHintTextview = (TextView) mHeaderView.findViewById(R.id.xlistview_header_hint_textview);//头布局中显示时间的控件mXlistviewHeaderTime = (TextView) mHeaderView.findViewById(R.id.xlistview_header_time);//头布局中显示的指示箭头mXlistviewHeaderArrow = (ImageView) mHeaderView.findViewById(R.id.xlistview_header_arrow);//头布局中显示的加载圆形进度条mXlistviewHeaderProgressbar = (ProgressBar) mHeaderView.findViewById(R.id.xlistview_header_progressbar);

当头布局出现在屏幕上,但是还没有完全显示在屏幕上的时候,指示箭头应当向下,状太信息应当为下拉刷新

当头布局完全显示在屏幕上的时候,指示箭头指示方向向上,状态为释放刷新

//更新头布局的方法private void updateHeaderView() {switch (header_current_state) {case PULL_REFRESH_STATE:   //下拉刷新状态//[1]更改iv状态mXlistviewHeaderArrow.startAnimation(downAnimation);//[2]设置 tv_update 状态mXlistviewHeaderHintTextview.setText("下拉刷新");//[3]隐藏头布局mHeaderView.setPadding(0, -mHeaderHeight, 0, 0);break;case RELEASE_STATE:        //释放刷新状态mXlistviewHeaderArrow.startAnimation(upAnimation);mXlistviewHeaderHintTextview.setText("释放刷新");break;case RELEASEING:           //正在刷新的状态//[1]把动画图片隐藏mXlistviewHeaderArrow.setVisibility(View.INVISIBLE);mXlistviewHeaderArrow.clearAnimation();//[2]显示进度条mXlistviewHeaderProgressbar.setVisibility(View.VISIBLE);//[3]刷新状态的文字改为 正在刷新mXlistviewHeaderHintTextview.setText("正在刷新ing");//[4]设置头布局回到屏幕顶部mHeaderView.setPadding(0, 0, 0, 0);break;}

在onTouchEvent中处理ACTION_UP事件

如果当前的状态是释放刷新,那当手指抬起的时候,我们将要进行正在刷新状态,并进行相关UI显示更新操作

case MotionEvent.ACTION_UP:if (header_current_state == PULL_REFRESH_STATE) {updateHeaderView();}else if (header_current_state == RELEASE_STATE) {//[1]把正在刷新状态 赋值给 当前状态header_current_state = RELEASEING;//[2]调用更新头布局的方法updateHeaderView();//[3]更新为下拉状态
//              header_current_state =PULL_REFRESH_STATE;}break;

可以看到上面使用到了将指示箭头进行旋转操作的动画,可以在构造中进行初始化操作

 private RotateAnimation upAnimation;private RotateAnimation downAnimation;//初始化头布局 图片旋转的动画private void initAnim() {//向上旋转的动画upAnimation = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);upAnimation.setDuration(500);//设置动画执行的时长upAnimation.setFillAfter(true);//向下旋转的动画downAnimation = new RotateAnimation(-180, -360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);downAnimation.setDuration(500);//设置动画执行的时长downAnimation.setFillAfter(true);}

七 设置下拉刷新的监听回调接口

 //设置下拉刷新数据的接口public interface OnPullDownRefreshListener{public void onPullDownRefresh();}private  OnPullDownRefreshListener mOnPullDownRefreshListener;//设置刷新的监听public void setOnPullDownRefreshListener(OnPullDownRefreshListener listener){mOnPullDownRefreshListener = listener;}

然后在onTouchEvent方法中的ACTION_UP事件中片回调

   if (mOnPullDownRefreshListener!=null) {mOnPullDownRefreshListener.onRefresh();}

八 设置加载数据完成后,隐藏头布局并更新显示时间

ublic void setOnLoadFinish() {//[0]进度条隐藏 mXlistviewHeaderProgressbar.setVisibility(View.INVISIBLE);//[2]在这里更新时间 mXlistviewHeaderTime.setText(getCurrentTimerr());//[3]隐藏头布局mHeaderView.setPadding(0, -mHeaderHeight, 0, 0);//[4]把状态置为下拉状态 header_current_state = PULL_REFRESH_STATE;}

也就是说当我们的数据更新完毕后,需要调用我们设置的方法将显示刷新头布局隐藏,并更新相应的状态与显示信息

更新刷新显示的时间 :

public String getCurrentTimerr(){SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");return sdf.format(new Date());}

到这里,我们的这个完整的具有下拉刷新功能的ListView就可以进行使用了

九 添加上拉加载更多数据功能

private void initFootView() {//[1]通过打气筒把一个布局转换成一个view对象mfootView = View.inflate(getContext(), R.layout.xlistview_footer, null);mfootView.measure(0, 0);footHeight = mfootView.getMeasuredHeight();//[1]默认情况隐藏脚布局mfootView.setPadding(0, -footHeight, 0, 0);//[2]添加脚布局this.addFooterView(mfootView);//[3]给listview设置滑动监听this.setOnScrollListener(this);}

脚布局文件中 :

<pre name="code" class="html"><?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="fill_parent"android:layout_height="wrap_content"android:padding="10dp" ><TextViewandroid:id="@+id/xlistview_footer_hint_textview"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:text="@string/xlistview_footer_hint_normal" /><ProgressBarandroid:layout_toLeftOf="@id/xlistview_footer_hint_textview"android:id="@+id/xlistview_footer_progressbar"android:layout_width="wrap_content"android:layout_height="wrap_content"android:visibility="visible" /></RelativeLayout>

可以看到这里设置了一个滑动监听,在这里我们需要将我们的控件实现滑动监听事件

public class RefreshListView  extends ListView implements AbsListView.OnScrollListener {...@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {}@Overridepublic void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {}
}

设置上拉加载更多的回调监听

 private OnUpLoadingMoreListener mOnUpLoadingMoreListener;public void setOnLoadingMoreListener(OnUpLoadingMoreListener l){mOnUpLoadingMoreListener = l;}public interface OnUpLoadingMoreListener{public void onLoadingMore();}

在listView的滑动监听事件中回调监听方法

@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {if (scrollState== SCROLL_STATE_IDLE ||scrollState == SCROLL_STATE_FLING) {//判断lisview 是否滑动到了底部if (getLastVisiblePosition()==getCount()-1 ) {//[1]把脚布局显示出来mfootView.setPadding(0, 0, 0, 0);if (mOnUpLoadingMoreListener!=null) {mOnUpLoadingMoreListener.onLoadingMore();}}}}

设置加载完成后调用方法来隐藏加载更多的显示布局

 //加载更多完成 需要处理的逻辑public void setOnLoadIngMoreFinish() {//[1]把加载更多脚布局隐藏mfootView.setPadding(0, -footHeight, 0, 0);}

点击下载源码

下载密码:uvfr

Android ListView 疯狂之旅  第一季     《自定义侧拉删除》 点击打开链接查看
Android ListView 疯狂之旅  第二季     《分组排序显示数据》   点击打开链接查看

最新脑筋急转:  男人与女人一起比赛猜智力题 ,一般女人会赢,因为”难得糊涂“,男的糊涂

Android ListView 疯狂之旅 之 《自定义下拉刷新功能的ListView》相关推荐

  1. Android RecyclerView(八)设置自定义 下拉刷新 与 上拉加载数据

    Android RecyclerView(八)设置下拉刷新 与 上拉加载数据 GitHub 项目源码 CSDN 博客说明 智慧安卓App 文章分析 下拉刷新效果 上拉加载数据效果 1 xml布局文件中 ...

  2. android listview下拉动画效果,Android开发中利用ListView实现一个渐变式的下拉刷新动画...

    Android开发中利用ListView实现一个渐变式的下拉刷新动画 发布时间:2020-11-23 16:50:31 来源:亿速云 阅读:80 作者:Leah 本篇文章给大家分享的是有关Androi ...

  3. Android自定义组合控件---教你如何自定义下拉刷新和左滑删除

    绪论 最近项目里面用到了下拉刷新和左滑删除,网上找了找并没有可以用的,有比较好的左滑删除,但是并没有和下拉刷新上拉加载结合到一起,要不就是一些比较水的结合,并不能在项目里面使用,小编一着急自己组合了一 ...

  4. Android自定义下拉刷新动画--仿百度外卖下拉刷新

    好久没写博客了,小编之前一段时间一直在找工作,从天津来到了我们的大帝都,感觉还不错.好了废话不多说了,开始我们今天的主题吧.现如今的APP各式各样,同样也带来了各种需求,一个下拉刷新都能玩出花样了,前 ...

  5. Android m 自定义下拉菜单,Android实现动画效果的自定义下拉菜单功能

    我们在购物APP里面设置收货地址时,都会有让我们选择省份及城市的下拉菜单项.今天我将使用Android原生的 Spinner 控件来实现一个自定义的下拉菜单功能,并配上一个透明渐变动画效果. 要实现的 ...

  6. Android下拉刷新完全解析,教你如何一分钟实现下拉刷新功能 (转)

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/9255575 最 近项目中需要用到ListView下拉刷新的功能,一开始想图省事,在 ...

  7. Xamarin. Android实现下拉刷新功能

    PS:发现文章被其他网站或者博客抓取后发表为原创了,给图片加了个水印 下拉刷新功能在安卓和iOS中非常常见,一般实现这样的功能都是直接使用第三方的库,网上能找到很多这样的开源库.然而在Xamarin. ...

  8. 自定义下拉刷新之仿AcFun下拉刷新

    俗话说好记性不如烂笔头,决定以后将研究过的东西写到博客里,方便自己以后查找,也方便技术分享.第一篇从基础的自定义下拉刷新开始.这里说下,我是在大神的肩膀上进行自定义的,因为自己重写下拉刷新的话会有很多 ...

  9. android官方自带下拉刷新功能

    最近想写下拉刷新功能,网上找的第三方框架最著名的pullToRefresh也早在2013年停止维护了,偶然间发现谷歌公司早已推出了自家的下拉刷新功能,位于v4包中,效果请看下图: 使用的就是andro ...

最新文章

  1. 边缘检测robert原理_机器视觉边缘模式检测应用
  2. vue2项目使用codemirror插件实现代码编辑器功能
  3. 对于大型公司项目平台选择j2ee的几层认识
  4. nginx设置 二级域名 指定端口
  5. linux程序多少位,查看linux版本是多少位
  6. 微信支付官方SDK V3 .NET版的坑
  7. 博客园的祥和需要大家共同努力
  8. 数据分析汇报用这个神器,让他们弃用了Excel和PPT
  9. 防止ViewPager中的Fragment被销毁的方法
  10. 题目1080:进制转换(任意进制直接转换方法)
  11. Java操作MongoDB(聚合函数)向Mongo插入及查询数据
  12. AI界的革命!终于可以自动标注了!
  13. fbinstool linux iso,大神给你传授fbinsttool下载 【操作教程】 的详细_
  14. pepe:从Pastebin收集邮件地址的信息
  15. Scheme 语言概要(上)
  16. 厦大2021级期末上机考试
  17. 软件开发视频资源分享
  18. 如何通过AWS Route53注册域名
  19. Windows 消息机制浅析
  20. 百科!生产计划如何在生产管理软件中制定

热门文章

  1. 零基础快速入门python教程,结合新手练习的5大项目
  2. linux apache配置_linux查看nginx、apache、php、php-fpm、mysql及配置项所在目录
  3. 收藏 | 小目标检测的一些问题,思路和方案
  4. 收藏 | 一文看懂注意力机制
  5. 2018年90后薪资报告出炉:你在哪个级别???
  6. 疯狂为《英伟达深度学习学院半日免费初级课程》打Call
  7. java list 取几个字段组装成map_java.util.concurrent 并发包诸类概览
  8. rsa java模数_RSA公私钥获取模数和质数
  9. php点击标题进入_重新学习php基础之-E-mail(十八)
  10. wdos8系统服务器丢失,win8一键修复丢失DLL,常见dll丢失一键修复办法