指令汇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 ...
随机推荐
- 【Miller-Rabin随机判素数算法】
实用性介绍: #include<bits/stdc++.h> #define go(i,a,b) for(int i=a;i<=b;i++) #define T 5 #define ...
- [ Java学习基础 ] Java构造函数
构造方法是类中特殊方法,用来初始化类的实例变量,它在创建对象(new运算符)之后自动调用. Java构造方法的特点如下: 构造方法名必须与类名相同. 构造方法没有任何返回值,包括void. 构造方法只 ...
- RabbitMQ-Spring AMQP
上篇文章RabbitMQ基础入门学习了rabbitMQ一些基础的api,当然spring也在原生代码的基础上做了更多的封装,这篇文章就基于spring-rabbit,学习一下spring的实现. p. ...
- Express 配置 https / 443 安全链接
按照教程已配置成功 前一部分内容参照 https://blog.csdn.net/chenyufeng1991/article/details/60340006 前半部分是生成证书文件,关键部 ...
- SQl语句中使用占位符的优点
1.增加SQL代码可读性2.占位符可以预先编译,提高执行效率3.防止SQL注入4用占位符的目的是绑定变量,这样可以减少数据SQL的硬解析,所以执行效率会提高不少 绑定变量是Oracle解决硬解析的首要 ...
- VS生成项目时,有些文件无法复制到输出目录的解决办法
有时候,我们在生成项目时,发现有些文件如:.jpg的图片文件,无法复制到输出目录中,此时会非常纠结,反复的清理项目,重新生成,依旧不能解决此问题.后来我打开.csproj的项目工程文件时,经过对比发现 ...
- WEB中间件--Jboss未授权访问,
1,Jboss未授权访问部署木马 发现存在Jboss默认页面,点进控制页 点击 Jboss.deployment 进入应用部署页面 也可以直接输入此URL进入 http://www.ctfswiki. ...
- http协议无状态中的 "状态" 到底指的是什么?!
引子: 最近在好好了解http,发现对介绍http的第一句话[http协议是无状态的,无连接的]就无法理解了:无状态的[状态]到底指的是什么?! 找了很多资料不仅没有发现有一针见血正面回答这个问题的, ...
- 详解Tomcat配置JVM参数步骤
这里向大家描述一下如何使用Tomcat配置JVM参数,Tomcat本身不能直接在计算机上运行,需要依赖于硬件基础之上的操作系统和一个Java虚拟机.您可以选择自己的需要选择不同的操作系统和对应的JDK ...
- 毕业回馈-89c51之定时器/计数器(Timer/Count)
今天分享的是89c51系列单片机的内部资源定时器/计数器,在所有的嵌入式系统中都包含这两个内部功能. 首先先了解几个定时器/计数器相关的概念: •时钟周期:时钟周期 T 是时序中最小的时间单位,具体计 ...