现在我们继续这个新闻客户端的开发,今天分享的是下拉刷新的实现,我们都知道下拉刷新是一个应用很常见也很实用的功能。我这个应用是通过拉ListView来实现刷新的,先看一张刷新的原理图

从图中可知,手指移动的距离就是dy。

刷新分为三种状态:下拉刷新、正在刷新、松开刷新;

定义这三种状态为:

private static final int STATE_PULL_REFRESH = 0;// 下拉刷新

private static final int STATE_RELEASE_REFRESH = 1;// 松开刷新

private static final int STATE_REFRESHING = 2;// 正在刷新

接下来开始写我们的代码了

初始化头布局:

private void initHeaderView() {
mHeaderView = View.inflate(getContext(), R.layout.refresh_header, null);
this.addHeaderView(mHeaderView); tvTitle = (TextView) mHeaderView.findViewById(R.id.tv_title);
tvTime = (TextView) mHeaderView.findViewById(R.id.tv_time);
ivArrow = (ImageView) mHeaderView.findViewById(R.id.iv_arr);
pbProgress = (ProgressBar) mHeaderView.findViewById(R.id.pb_progress); mHeaderView.measure(0, 0);
mHeaderViewHeight = mHeaderView.getMeasuredHeight(); mHeaderView.setPadding(0, -mHeaderViewHeight, 0, 0);// 隐藏头布局 initArrowAnim(); tvTime.setText("最后刷新时间:" + getCurrentTime());
}

初始化脚布局

 * 初始化脚布局
*/
private void initFooterView() {
mFooterView = View.inflate(getContext(),
R.layout.refresh_listview_footer, null);
this.addFooterView(mFooterView); mFooterView.measure(0, 0);
mFooterViewHeight = mFooterView.getMeasuredHeight(); mFooterView.setPadding(0, -mFooterViewHeight, 0, 0);// 隐藏 this.setOnScrollListener(this);
}

初始化箭头的动画:

/**
* 初始化箭头动画
*/
private void initArrowAnim() {
// 箭头向上动画
animUp = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
animUp.setDuration(200);
animUp.setFillAfter(true); // 箭头向下动画
animDown = new RotateAnimation(-180, 0, Animation.RELATIVE_TO_SELF,
0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
animDown.setDuration(200);
animDown.setFillAfter(true); }

接下来是实现触摸的方法及偏移量的计算:

@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
startY = (int) ev.getRawY();
break;
case MotionEvent.ACTION_MOVE:
if (startY == -1) {// 确保startY有效
startY = (int) ev.getRawY();
} if (mCurrrentState == STATE_REFRESHING) {// 正在刷新时不做处理
break;
} int endY = (int) ev.getRawY();
int dy = endY - startY;// 移动偏移量 if (dy > 0 && getFirstVisiblePosition() == 0) {// 只有下拉并且当前是第一个item,才允许下拉
int padding = dy - mHeaderViewHeight;// 计算padding
mHeaderView.setPadding(0, padding, 0, 0);// 设置当前padding if (padding > 0 && mCurrrentState != STATE_RELEASE_REFRESH) {// 状态改为松开刷新
mCurrrentState = STATE_RELEASE_REFRESH;
refreshState();
} else if (padding < 0 && mCurrrentState != STATE_PULL_REFRESH) {// 改为下拉刷新状态
mCurrrentState = STATE_PULL_REFRESH;
refreshState();
} return true;
} break;
case MotionEvent.ACTION_UP:
startY = -1;// 重置 if (mCurrrentState == STATE_RELEASE_REFRESH) {
mCurrrentState = STATE_REFRESHING;// 正在刷新
mHeaderView.setPadding(0, 0, 0, 0);// 显示
refreshState();
} else if (mCurrrentState == STATE_PULL_REFRESH) {
mHeaderView.setPadding(0, -mHeaderViewHeight, 0, 0);// 隐藏
} break; default:
break;
}
return super.onTouchEvent(ev);
}

刷新下拉控件的布局:

private void refreshState() {
switch (mCurrrentState) {
case STATE_PULL_REFRESH:
tvTitle.setText("下拉刷新");
ivArrow.setVisibility(View.VISIBLE);
pbProgress.setVisibility(View.INVISIBLE);
ivArrow.startAnimation(animDown);
break;
case STATE_RELEASE_REFRESH:
tvTitle.setText("松开刷新");
ivArrow.setVisibility(View.VISIBLE);
pbProgress.setVisibility(View.INVISIBLE);
ivArrow.startAnimation(animUp);
break;
case STATE_REFRESHING:
tvTitle.setText("正在刷新...");
ivArrow.clearAnimation();// 必须先清除动画,才能隐藏
ivArrow.setVisibility(View.INVISIBLE);
pbProgress.setVisibility(View.VISIBLE); if (mListener != null) {
mListener.onRefresh();
}
break; default:
break;
}
}

刷新完成之后我们需要收起这个下拉刷新的按钮,额,好吧,总的来说比较复杂了:

/*
* 收起下拉刷新的控件
*/
public void onRefreshComplete(boolean success) {
if (isLoadingMore) {// 正在加载更多...
mFooterView.setPadding(0, -mFooterViewHeight, 0, 0);// 隐藏脚布局
isLoadingMore = false;
} else {
mCurrrentState = STATE_PULL_REFRESH;
tvTitle.setText("下拉刷新");
ivArrow.setVisibility(View.VISIBLE);
pbProgress.setVisibility(View.INVISIBLE); mHeaderView.setPadding(0, -mHeaderViewHeight, 0, 0);// 隐藏 if (success) {
tvTime.setText("最后刷新时间:" + getCurrentTime());
}
}
}

我们还可以看到上面有一个实时的时间,获取当前系统时间:

/**
* 获取当前时间
*/
public String getCurrentTime() {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return format.format(new Date());
} private boolean isLoadingMore; @Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == SCROLL_STATE_IDLE
|| scrollState == SCROLL_STATE_FLING) { if (getLastVisiblePosition() == getCount() - 1 && !isLoadingMore) {// 滑动到最后
// System.out.println("到底了.....");
mFooterView.setPadding(0, 0, 0, 0);// 显示
setSelection(getCount() - 1);// 改变listview显示位置 isLoadingMore = true; if (mListener != null) {
mListener.onLoadMore();
}
}
}
}

在新闻详情页里面要设置一下下拉刷新监听:

// 设置下拉刷新监听
lvList.setOnRefreshListener(new OnRefreshListener() { @Override
public void onRefresh() {
getDataFromServer();
} @Override
public void onLoadMore() {
if (mMoreUrl != null) {
getMoreDataFromServer();
} else {
Toast.makeText(mActivity, "最后一页了", Toast.LENGTH_SHORT)
.show();
lvList.onRefreshComplete(false);// 收起加载更多的布局
}
}
});

这里刷新功能基本上实现了,这里只写出了关键代码。

指令汇B新闻客户端开发(三) 下拉刷新的更多相关文章

  1. 指令汇B新闻客户端开发(四) 自动轮播条

    在这个新闻客户端,我们可以看到有一个轮播页面,在这个项目中,用Handler和一个定时器来做更容易一些, 我们定义一个Handler: private Handler mHandler; 定时器的代码 ...

  2. 指令汇B新闻客户端开发(二) 主页面布局

    这个主页面采用了一个开源框架SlidingMenu,这个可以在git上面下载.把这些下载下来的文件import我们的eclipse中,用我们的项目去加载这个library,在这个过程中很有可能会报错, ...

  3. 指令汇B新闻客户端开发(六) 浅谈屏幕适配解决方案

    屏幕适配的问题,我相信很多大牛的经验远比我丰富,在此就简单的分享一下我所做的的屏幕适配方案,当然我说的是安卓方面的啦,嘿嘿,屏幕适配我们一般用1280*720的屏幕作为我们的主流开发屏,当然现在And ...

  4. 指令汇B新闻客户端开发(一) 新手引导页开发

    首先做开发的时候应该有一个闪屏页面和新手引导页, 我相信闪屏页面大家应该都会了,那么先看到新手引导页了. 我们可以看到这其实是一个ViewPager,我们也可以看到这是3个引导页,那么首先来看一下布局 ...

  5. 指令汇B新闻客户端开发(五) ShareSdk的使用

    ShareSdk是一个分享按钮的开源框架,我们首先可以去mob的官网下载这个控件.mob官网,然后找到sdk下载那一栏, 下载下来之后点击这个.jar文件就会有一个弹窗,填写自己的应用包名和要哪些分享 ...

  6. Windows phone应用开发[18]-下拉刷新

    在windows phone 中采用数据列表时为了保证用户体验常遇到加载数据的问题.这个问题普遍到只要你用到数据列表就要早晚面对这个问题. 很多人会说这个问题已经有解决方案. 其实真正问题并不在于如何 ...

  7. android124 zhihuibeijing 新闻中心-新闻 -北京页签 下拉刷新

    缓存工具类:以url为key,json数据为value, package com.itheima.zhbj52.utils; import com.itheima.zhbj52.global.Glob ...

  8. iOS开发-UIRefreshControl下拉刷新

    下拉刷新一直都是第三库的天下,有的第三库甚至支持上下左右刷新,UIRefreshControl是iOS6之后支持的一个刷新控件,不过由于功能单一,样式不能自定义,因此不能满足大众的需求,用法比较简单在 ...

  9. 微信小程序云开发-列表下拉刷新

    一.json文件开启页面刷新 开启页面刷新.在页面的json文件里配置两处: "enablePullDownRefresh": true, //true代表开启页面下拉刷新 &qu ...

随机推荐

  1. [SCOI 2016]美味

    Description 题库链接 给你一个长度为 \(n\) 的序列 \(A\) . \(m\) 组询问 \((b,x,l,r)\) 询问 \[\max_{i=l}^r b\oplus (A_i+x) ...

  2. [CQOI 2011]动态逆序对

    Description 题库链接 对于序列 \(A\) ,它的逆序对数定义为满足 \(i<j\) ,且 \(A_i>A_j\) 的数对 \((i,j)\) 的个数.给 \(1\) 到 \( ...

  3. [HNOI2016]序列

    题目描述 给定长度为n的序列:a1,a2,...,an,记为a[1:n].类似地,a[l:r](1<=l<=r<=N)是指序 列:al,al+1,...,ar-1,ar.若1< ...

  4. [POI2006]ORK-Ploughing

    Description Byteasar想耕种他那块矩形的田,他每次能耕种矩形的一边(上下左右都行),在他每次耕完后,剩下的田也一定是矩形,每块小区域边长为1,耕地的长宽分别为m和n,不幸的是Byte ...

  5. Postgres中postmaster代码解析(中)

    今天我们对postmaster的以下细节进行讨论: backend的启动和client的连接请求的认证 客户端取消查询时的处理 接受pg_ctl的shutdown请求进行shutdown处理 2.与前 ...

  6. salesforce lightning零基础学习(二) lightning 知识简单介绍----lightning事件驱动模型

    看此篇博客前或者后,看一下trailhead可以加深印象以及理解的更好:https://trailhead.salesforce.com/modules/lex_dev_lc_basics 做过cla ...

  7. jquery 跨域请求数据问题

    昨天参加了一个前端的面试,被问到一个跨域请求数据问题,我们之前一直用的是apicloud的api进行请求的,跨域是被apicloud封装起来的,也就没有注意跨域请求数据的问题.当被问到用jquery跨 ...

  8. JS中怎样判断undefined(比较不错的方法)

    最近做项目碰到的问题.拿出来跟大家分享一下吧. 用servlet赋值给html页面文本框值后,用alert来弹出这个值.结果显示"undefined".所以我就自然的用这个值和字符 ...

  9. setTimeout、setInterval被遗忘的第三个参数

    一.最近在看promise,惊奇的发现:原来 setTimeout不只有两个参数,我还能说什么呢?赶紧探探究竟. function multiply(input) { return new Promi ...

  10. Ubuntu16.04下安装jdk1.8过程

    笔者环境:腾讯云服务器 Ubuntu16.04 x64 一 . 去oracle官网下载对应的jdk 下载地址:http://www.oracle.com/technetwork/java/javase ...