指令汇B新闻客户端开发(三) 下拉刷新
现在我们继续这个新闻客户端的开发,今天分享的是下拉刷新的实现,我们都知道下拉刷新是一个应用很常见也很实用的功能。我这个应用是通过拉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新闻客户端开发(三) 下拉刷新的更多相关文章
- 指令汇B新闻客户端开发(四) 自动轮播条
在这个新闻客户端,我们可以看到有一个轮播页面,在这个项目中,用Handler和一个定时器来做更容易一些, 我们定义一个Handler: private Handler mHandler; 定时器的代码 ...
- 指令汇B新闻客户端开发(二) 主页面布局
这个主页面采用了一个开源框架SlidingMenu,这个可以在git上面下载.把这些下载下来的文件import我们的eclipse中,用我们的项目去加载这个library,在这个过程中很有可能会报错, ...
- 指令汇B新闻客户端开发(六) 浅谈屏幕适配解决方案
屏幕适配的问题,我相信很多大牛的经验远比我丰富,在此就简单的分享一下我所做的的屏幕适配方案,当然我说的是安卓方面的啦,嘿嘿,屏幕适配我们一般用1280*720的屏幕作为我们的主流开发屏,当然现在And ...
- 指令汇B新闻客户端开发(一) 新手引导页开发
首先做开发的时候应该有一个闪屏页面和新手引导页, 我相信闪屏页面大家应该都会了,那么先看到新手引导页了. 我们可以看到这其实是一个ViewPager,我们也可以看到这是3个引导页,那么首先来看一下布局 ...
- 指令汇B新闻客户端开发(五) ShareSdk的使用
ShareSdk是一个分享按钮的开源框架,我们首先可以去mob的官网下载这个控件.mob官网,然后找到sdk下载那一栏, 下载下来之后点击这个.jar文件就会有一个弹窗,填写自己的应用包名和要哪些分享 ...
- Windows phone应用开发[18]-下拉刷新
在windows phone 中采用数据列表时为了保证用户体验常遇到加载数据的问题.这个问题普遍到只要你用到数据列表就要早晚面对这个问题. 很多人会说这个问题已经有解决方案. 其实真正问题并不在于如何 ...
- android124 zhihuibeijing 新闻中心-新闻 -北京页签 下拉刷新
缓存工具类:以url为key,json数据为value, package com.itheima.zhbj52.utils; import com.itheima.zhbj52.global.Glob ...
- iOS开发-UIRefreshControl下拉刷新
下拉刷新一直都是第三库的天下,有的第三库甚至支持上下左右刷新,UIRefreshControl是iOS6之后支持的一个刷新控件,不过由于功能单一,样式不能自定义,因此不能满足大众的需求,用法比较简单在 ...
- 微信小程序云开发-列表下拉刷新
一.json文件开启页面刷新 开启页面刷新.在页面的json文件里配置两处: "enablePullDownRefresh": true, //true代表开启页面下拉刷新 &qu ...
随机推荐
- [HNOI 2001]矩阵乘积
Description Input Output Sample Input 1 2 3 4 2 3 1 1 3 1 4 5 2 2 1 3 1 2 1 2 2 2 1 1 3 1 2 3 2 4 1 ...
- [SDOI2016]硬币游戏
题目描述 Alice 和 Bob 现在在玩的游戏,主角是依次编号为 1 到 n 的 n 枚硬币.每一枚硬币都有两面,我们分别称之为正面和反面.一开始的时候,有些硬币是正面向上的,有些是反面朝上的.Al ...
- POJ2454 Jersey Politics
Description In the newest census of Jersey Cows and Holstein Cows, Wisconsin cows have earned three ...
- 【Codeforces Round 431 (Div. 2) A B C D E五个题】
先给出比赛地址啦,感觉这场比赛思维考察非常灵活而美妙. A. Odds and Ends ·述大意: 输入n(n<=100)表示长度为n的序列,接下来输入这个序列.询问是否可以将序列划 ...
- hdu 5532(最长上升子序列)
Input The first line contains an integer T indicating the total number of test cases. Each test case ...
- SpringCloud学习之DiscoveryClient探究
当我们使用@DiscoveryClient注解的时候,会不会有如下疑问:它为什么会进行注册服务的操作,它不是应该用作服务发现的吗?下面我们就来深入的来探究一下其源码. 一.Springframewor ...
- Dubbo介绍和服务架构分析
Dubbo是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和Spring框架无缝集成.使用zookeeper作为服务的注册中心,对外提供服务 ...
- reload(sys)后print失效问题解决
python版本: python2.7.6 #查看python默认编码格式 >>> import sys >>> print sys.getdefaultencod ...
- Java不走弯路教程(2.Hello,Java!)
2.Hello,Java! 欢迎来到Java的世界,在上一章,我们已经完成了DOS的基本操作学习和Java的环境搭建,在本章中我们Java来完成一个简单的DOS程序. 2.1 Hello,Java! ...
- Node.js 定时器
稳定性: 5 - 锁定 所有的定时器函数都是全局的.不需要通过 require() 就可以访问. setTimeout(callback, delay[, arg][, ...]) delay 毫秒之 ...