Android中实现List下拉刷新
2015-07-16 14:27
567 查看
今天,我以如何在Android中实现下拉刷新介绍下主要实现步骤:
1.重写ListView。ListView中有一个addHeaderView()的方法用来在顶部添加一个view。
2.让ListView实现触摸事件和滚动事件,来根据状态动态改变view。
3.利用回调接口来更新ListView。
下面看具体代码:
public class RefreshListView extends ListView implements OnScrollListener{
private View headerView;
private int headerViewHeight;
private int firstVisibleItem;//当前第一个可见的Item的位置
private boolean mark;//标记:当前是否在ListView的最顶端按下的
private int startY;//按下时的Y值
private int state;//当前的状态
private final int NONE = 0;//正常状态
private final int PULL = 1;//提示下拉状态
private final int RELESE = 2;//松开释放的状态
private final int REFLASHING = 3;//正在刷新的状态
private int scrollState;//当前滚动状态
private RefreshInterface refreshInterface;
public RefreshListView(Context context) {
super(context);
initView(context);
}
public RefreshListView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
public RefreshListView(Context context, AttributeSet attrs,int defStyle) {
// TODO Auto-generated constructor stub
super(context,attrs,defStyle);
initView(context);
}
/**
* 初始化组件 添加顶部布局文件到ListView
* @param context
*/
private void initView(Context context){
headerView = LayoutInflater.from(context).inflate(R.layout.header_listview, null);
measureView(headerView);
headerViewHeight = headerView.getMeasuredHeight();//此处需要通知父布局headerView占的宽高。
topPadding(-headerViewHeight);
this.addHeaderView(headerView);
this.setOnScrollListener(this);
}
/**
* 通知父布局view所占的宽高
* @param view
*/
private void measureView(View view){
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
if(layoutParams == null){
layoutParams = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
}
//获取宽高
int width = ViewGroup.getChildMeasureSpec(0, 0,layoutParams.width);
int height;
int tempHeight = layoutParams.height;
if(tempHeight > 0){
height = MeasureSpec.makeMeasureSpec(tempHeight, MeasureSpec.EXACTLY);
}else{
height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
}
//填充View
view.measure(width, height);
}
/**
* 设置headerView的上边距
* @param topPadding
*/
private void topPadding(int topPadding){
headerView.setPadding(headerView.getPaddingLeft(),
topPadding ,
headerView.getPaddingRight(),
headerView.getPaddingBottom());
headerView.invalidate();
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub
this.scrollState = scrollState;
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
this.firstVisibleItem = firstVisibleItem;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
//按下
case MotionEvent.ACTION_DOWN:
if(firstVisibleItem == 0){
//第一项Item在最顶端
mark = true;
startY = (int)event.getY();
}
break;
//弹起
case MotionEvent.ACTION_UP:
if(state == RELESE){
state = REFLASHING;
//加载最新数据
reflashView();
refreshInterface.onRefresh();
}else if(state == PULL){
state = NONE;
mark = false;
reflashView();
}
break;
//移动
case MotionEvent.ACTION_MOVE:
move(event);
break;
default:
break;
}
return super.onTouchEvent(event);
}
private void move(MotionEvent event){
if(!mark){
return;
}
int currentY = (int)event.getY();
int space = currentY - startY;
int topPadding = space - headerViewHeight;
switch (state) {
case NONE:
if(space > 0){
state = PULL;
reflashView();
}
break;
case PULL:
topPadding(topPadding);
if(space > headerViewHeight + 30 && scrollState == SCROLL_STATE_TOUCH_SCROLL){
state = RELESE;
reflashView();
}
break;
case RELESE:
topPadding(topPadding);
if(space < headerViewHeight + 30 ){
state = PULL;
reflashView();
}else if(space <= 0){
state = NONE;
mark = false;
reflashView();
}
break;
default:
break;
}
}
//根据状态更新显示
private void reflashView(){
TextView textView = (TextView)findViewById(R.id.tip);
ImageView arrow = (ImageView)findViewById(R.id.refresh_arrow);
ProgressBar progress = (ProgressBar)findViewById(R.id.progress);
RotateAnimation animationDown = new RotateAnimation(
0,
180,
RotateAnimation.RELATIVE_TO_SELF,
0.5f,
RotateAnimation.RELATIVE_TO_SELF,
0.5f);
RotateAnimation animationUp = new RotateAnimation(
180,
0,
RotateAnimation.RELATIVE_TO_SELF,
0.5f,
RotateAnimation.RELATIVE_TO_SELF,
0.5f);
animationDown.setDuration(500);
animationDown.setFillAfter(true);
animationUp.setDuration(500);
animationUp.setFillAfter(true);
switch (state) {
case NONE:
topPadding(-headerViewHeight);
arrow.clearAnimation();
break;
case PULL:
arrow.setVisibility(View.VISIBLE);
progress.setVisibility(View.GONE);
textView.setText("下拉可以刷新");
arrow.clearAnimation();
arrow.setAnimation(animationUp);
break;
case RELESE:
arrow.setVisibility(View.VISIBLE);
progress.setVisibility(View.GONE);
textView.setText("松开可以刷新");
arrow.clearAnimation();
arrow.setAnimation(animationDown);
break;
case REFLASHING:
topPadding(50);
arrow.setVisibility(View.GONE);
progress.setVisibility(View.VISIBLE);
textView.setText("正在刷新");
arrow.clearAnimation();
break;
default:
break;
}
}
/**
* 刷新完成
*/
public void refreshComplete(){
state = NONE;
mark = false;
TextView lastupdatetime = (TextView)findViewById(R.id.lastupdatetime);
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
Date date = new Date(System.currentTimeMillis());
String time = format.format(date);
lastupdatetime.setText(time);
reflashView();
}
/**
* 刷新数据接口
*/
public interface RefreshInterface{
public void onRefresh();
}
public void setInterface(RefreshInterface refreshInterface){
this.refreshInterface = refreshInterface;
}
}
1.重写ListView。ListView中有一个addHeaderView()的方法用来在顶部添加一个view。
2.让ListView实现触摸事件和滚动事件,来根据状态动态改变view。
3.利用回调接口来更新ListView。
下面看具体代码:
public class RefreshListView extends ListView implements OnScrollListener{
private View headerView;
private int headerViewHeight;
private int firstVisibleItem;//当前第一个可见的Item的位置
private boolean mark;//标记:当前是否在ListView的最顶端按下的
private int startY;//按下时的Y值
private int state;//当前的状态
private final int NONE = 0;//正常状态
private final int PULL = 1;//提示下拉状态
private final int RELESE = 2;//松开释放的状态
private final int REFLASHING = 3;//正在刷新的状态
private int scrollState;//当前滚动状态
private RefreshInterface refreshInterface;
public RefreshListView(Context context) {
super(context);
initView(context);
}
public RefreshListView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
public RefreshListView(Context context, AttributeSet attrs,int defStyle) {
// TODO Auto-generated constructor stub
super(context,attrs,defStyle);
initView(context);
}
/**
* 初始化组件 添加顶部布局文件到ListView
* @param context
*/
private void initView(Context context){
headerView = LayoutInflater.from(context).inflate(R.layout.header_listview, null);
measureView(headerView);
headerViewHeight = headerView.getMeasuredHeight();//此处需要通知父布局headerView占的宽高。
topPadding(-headerViewHeight);
this.addHeaderView(headerView);
this.setOnScrollListener(this);
}
/**
* 通知父布局view所占的宽高
* @param view
*/
private void measureView(View view){
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
if(layoutParams == null){
layoutParams = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
}
//获取宽高
int width = ViewGroup.getChildMeasureSpec(0, 0,layoutParams.width);
int height;
int tempHeight = layoutParams.height;
if(tempHeight > 0){
height = MeasureSpec.makeMeasureSpec(tempHeight, MeasureSpec.EXACTLY);
}else{
height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
}
//填充View
view.measure(width, height);
}
/**
* 设置headerView的上边距
* @param topPadding
*/
private void topPadding(int topPadding){
headerView.setPadding(headerView.getPaddingLeft(),
topPadding ,
headerView.getPaddingRight(),
headerView.getPaddingBottom());
headerView.invalidate();
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub
this.scrollState = scrollState;
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
this.firstVisibleItem = firstVisibleItem;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
//按下
case MotionEvent.ACTION_DOWN:
if(firstVisibleItem == 0){
//第一项Item在最顶端
mark = true;
startY = (int)event.getY();
}
break;
//弹起
case MotionEvent.ACTION_UP:
if(state == RELESE){
state = REFLASHING;
//加载最新数据
reflashView();
refreshInterface.onRefresh();
}else if(state == PULL){
state = NONE;
mark = false;
reflashView();
}
break;
//移动
case MotionEvent.ACTION_MOVE:
move(event);
break;
default:
break;
}
return super.onTouchEvent(event);
}
private void move(MotionEvent event){
if(!mark){
return;
}
int currentY = (int)event.getY();
int space = currentY - startY;
int topPadding = space - headerViewHeight;
switch (state) {
case NONE:
if(space > 0){
state = PULL;
reflashView();
}
break;
case PULL:
topPadding(topPadding);
if(space > headerViewHeight + 30 && scrollState == SCROLL_STATE_TOUCH_SCROLL){
state = RELESE;
reflashView();
}
break;
case RELESE:
topPadding(topPadding);
if(space < headerViewHeight + 30 ){
state = PULL;
reflashView();
}else if(space <= 0){
state = NONE;
mark = false;
reflashView();
}
break;
default:
break;
}
}
//根据状态更新显示
private void reflashView(){
TextView textView = (TextView)findViewById(R.id.tip);
ImageView arrow = (ImageView)findViewById(R.id.refresh_arrow);
ProgressBar progress = (ProgressBar)findViewById(R.id.progress);
RotateAnimation animationDown = new RotateAnimation(
0,
180,
RotateAnimation.RELATIVE_TO_SELF,
0.5f,
RotateAnimation.RELATIVE_TO_SELF,
0.5f);
RotateAnimation animationUp = new RotateAnimation(
180,
0,
RotateAnimation.RELATIVE_TO_SELF,
0.5f,
RotateAnimation.RELATIVE_TO_SELF,
0.5f);
animationDown.setDuration(500);
animationDown.setFillAfter(true);
animationUp.setDuration(500);
animationUp.setFillAfter(true);
switch (state) {
case NONE:
topPadding(-headerViewHeight);
arrow.clearAnimation();
break;
case PULL:
arrow.setVisibility(View.VISIBLE);
progress.setVisibility(View.GONE);
textView.setText("下拉可以刷新");
arrow.clearAnimation();
arrow.setAnimation(animationUp);
break;
case RELESE:
arrow.setVisibility(View.VISIBLE);
progress.setVisibility(View.GONE);
textView.setText("松开可以刷新");
arrow.clearAnimation();
arrow.setAnimation(animationDown);
break;
case REFLASHING:
topPadding(50);
arrow.setVisibility(View.GONE);
progress.setVisibility(View.VISIBLE);
textView.setText("正在刷新");
arrow.clearAnimation();
break;
default:
break;
}
}
/**
* 刷新完成
*/
public void refreshComplete(){
state = NONE;
mark = false;
TextView lastupdatetime = (TextView)findViewById(R.id.lastupdatetime);
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
Date date = new Date(System.currentTimeMillis());
String time = format.format(date);
lastupdatetime.setText(time);
reflashView();
}
/**
* 刷新数据接口
*/
public interface RefreshInterface{
public void onRefresh();
}
public void setInterface(RefreshInterface refreshInterface){
this.refreshInterface = refreshInterface;
}
}
相关文章推荐
- Android context空指针异常
- AndroidStudio百度地图开发之显示地图
- Android TextView(同时显示图片+文字)
- Android中Java和JavaScript交互
- Android中调用System.exit(0)
- android 双服务常驻后台:防止意见清理
- Android之退出整个应用的一种方法
- Android数据存储
- android 国内sdk下载地址及代理, android 环境搭建
- Android Activity 常用功能设置(全屏、横竖屏等)
- Android学习之播放背景音乐
- Activity生命周期的回调,你应该知道得更多!--Android源码剖析(下)
- Android 二维码 生成和识别(附Demo源码)
- Android仿IOS的AssistiveTouch的控件EasyTouch实现
- Android仿IOS的AssistiveTouch的控件EasyTouch实现
- Android编程规范与常用技巧
- Android学习之调用有道词典查词
- 收集-Android快速开发框架、第三方库
- 【Android学习】Merge 优化布局
- android---android:layout_weight属性