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);// 一开始的状态就是下拉刷新完的状态,所以为DONEstate = DONE;// 是否正在刷新isRefreshable = false;}@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {}@Overridepublic void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {if (firstVisibleItem == 0) {isRefreshable = true;} else {isRefreshable = false;}   }@Overridepublic 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的sizeif (state == PULL_To_REFRESH) {headerView.setPadding(0, -1 * headerContentHeight+ (tempY - startY) / RATIO, 0, 0);}// 更新headView的paddingTopif (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以及heightprivate 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" ><!-- 内容 --><RelativeLayoutandroid:id="@+id/head_contentLayout"android:layout_width="fill_parent"android:layout_height="wrap_content"android:paddingLeft="30dp" ><!-- 箭头图像、进度条 --><FrameLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentLeft="true"android:layout_centerVertical="true" ><!-- 箭头 --><ImageViewandroid:id="@+id/lvHeaderArrowIv"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:src="@drawable/arrow" /><!-- 进度条 --><ProgressBarandroid: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><!-- 提示、最近更新 --><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerHorizontal="true"android:gravity="center_horizontal"android:orientation="vertical" ><!-- 提示 --><TextViewandroid:id="@+id/lvHeaderTipsTv"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="下拉刷新"android:textColor="@color/white"android:textSize="20sp" /><!-- 最近更新 --><TextViewandroid: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.MyListViewandroid: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;@Overrideprotected 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() {@Overridepublic 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;}@Overrideprotected 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;}@Overridepublic int getCount() {return list.size();}@Overridepublic Object getItem(int position) {return list.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {TextView tv = new TextView(context.getApplicationContext());tv.setText(list.get(position));return tv;}}

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

求源码,请关注微信订阅号:smart_android,微信名:非著名程序员,关注成功后,给微信号发送您的邮箱,源码就会发到您的邮箱里。发送格式:发送内容+您的邮箱(内容即为你要的源码内容)

Android中ListView下拉刷新的实现相关推荐

  1. android中listView下拉刷新

    下拉刷新界面最初流行于iphone应用界面,如图:     然后在Android中也逐渐被应用,比如微博,资讯类.     所以,今天要实现的结果应该也是类似的,先贴出最终完成效果,如下图,接下来我们 ...

  2. android中上拉下滑布局,3年以上勿进!最简单的Android自定义ListView下拉刷新与上拉加载,代码直接拿去用~...

    本文主要针对开发新手,手写实现一个最简单Android自定义listview下拉刷新和上拉加载demo. 不喜可喷,欢迎大佬留言指点. 效果图 一:编写需要在ListView中增加头加载的布局文件,与 ...

  3. 浅谈Android列表ListView下拉刷新控件的实现(一)

    ListView下拉刷新的功能到处可见,很多app客户端都存在,比如QQ空间好友动态下拉刷新,网易新闻内容下拉刷新等.相信很多人已经把这个功能运用的很溜,妥妥的吧,接下就来实现一下功能,有个不爽的一点 ...

  4. Android实现ListView下拉刷新思路以及流程

    自定义ListView实现下拉刷新流程以及思路 前言:全局变量以及参数说明 (以及在刷新之后的接口回调说明) 1.下拉刷新状态 STATE_PULL_REFRESH (0 ) 2.释放刷新状态 STA ...

  5. ListView下拉刷新、上拉载入更多之封装改进

    在Android中ListView下拉刷新.上拉载入更多示例一文中,Maxwin兄给出的控件比较强大,前面有详细介绍,但是有个不足就是,里面使用了一些资源文件,包括图片,String,layout,这 ...

  6. 谷歌的android下拉刷新页面,Android SwipeRefreshLayout:谷歌官方SDK包中的下拉刷新

     <Android SwipeRefreshLayout:谷歌官方SDK包中的下拉刷新> 下拉刷新在如今移动开发中应用如此广泛和普遍,以至于谷歌干脆在SDK中给予支持.在android ...

  7. Android ListView下拉刷新时卡的问题解决小技巧

    问题:ListView下拉刷新时看上去非常的卡 解决方案: 在BaseAdapter的getView方法中,有三个参数 public View getView(int position, View c ...

  8. 基于Android的计步器(Pedometer)的讲解(六)——ListView下拉刷新页面

    计步器(Pedometer)整个项目的源代码,最近做了比较大的修改,可能以前下载的不能运行,感兴趣的朋友可以下载来看看(记得帮小弟在github打个星~) https://github.com/296 ...

  9. Flutter开发之ListView下拉刷新上拉加载更多(35)

    在Flutter开发之ListView组件(21) 文章中,我们了解了ListView组件的基本使用.但是数据比较少,没有涉及分页加载.而实际开发中,下拉刷新和分页加载几乎是所有APP的标配.在iOS ...

  10. android自带下拉阻尼动画,android 有阻尼下拉刷新列表的实现方法

    本文将会介绍有阻尼下拉刷新列表的实现,先来看看效果预览: 这是下拉状态: 这是下拉松开手指后listView回滚到刷新状态时的样子: 1. 如何调用 虽然效果图看起来样子不太好看,主要是因为那个蓝色的 ...

最新文章

  1. R语言使用ggplot2包使用geom_violin函数绘制分组小提琴图(分组颜色配置、位置配置)实战
  2. effectivec++条款18,让接口容易被正确使用,不宜被吴勇
  3. caffe data层_Caffe 学习:Eltwise层
  4. luogu P3808 【模板】AC自动机(简单版)
  5. 1.1 鞅、停时和域流-随机过程的可测性(布朗运动与随机计算【习题解答】)
  6. [云炬创业管理笔记]第6章制定创业行动测试5
  7. 第一节:数据库与数据仓库
  8. 详解 Linux环境中DHCP分配IP地址(实验详解)
  9. python 3 面向过程编程
  10. RDS关系型数据库服务
  11. 2018-3-10 unset 变量 ab测试
  12. 8片74151扩展为64选1数据选择器
  13. mouseover 和 mouseenter 的区别
  14. 网页中用到的对比原则(一):色彩对比
  15. QT 错误:Unable to create a debugging engine解决
  16. Python爬虫 selenium自动化 利用搜狗搜索爬取微信公众号文章信息
  17. fdisk分区详解【适用于2T以内的新硬盘分区】
  18. CMake设置Visual Studio工程的调试环境变量和工作目录cwd的方法
  19. 时序模型:长短期记忆网络(LSTM)
  20. 神经网络之误差反向传播法

热门文章

  1. AOP切面之实现计算器加减乘除--基于注解的方式
  2. 计算机硬盘解密,如何解除电脑硬盘密码 解除电脑硬盘密码方法【详解】
  3. 某班30名同学成绩c语言,.编程实现:求某班30个同学的所有成绩,并统计出其平均分,最高分和最低分。...
  4. 毕设 JAVA超市管理系统论文
  5. 如何在手机上查看SQLite文件
  6. kafka生产者实例配置参数
  7. 鸟哥惠新宸:PHP 7.1 的新特性我并不是很喜欢
  8. Iphone6+ 手机边框图片
  9. weex实现文本省略效果
  10. hacker 入门指南