Android下拉加载,上拉刷新的实现
2016-01-18 15:10
591 查看
曾经一度,自己因为实现此功能也是在看了各种网络资料,最终得以实现。今天闲来无事,就贴出代码,供像曾经的我一样的童鞋们参考参考
。话不多说贴代码了
自定义的RefreshListView
package com.zyd.pullupandrefresh.view;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.zyd.pullupandrefresh.R;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ProgressBar;
import android.widget.TextView;
/**
* @author YadiZheng
*
*/
public class RefreshListView extends ListView implements OnScrollListener {
private View headView;
private int height;
private int downY;
private final int PULL_REFRESH = 0;// 下拉刷新
private final int REALEASE_REFRESH = 1;// 松开刷新
private final int REFRESHING = 2;// 正在刷新
private int currentState = PULL_REFRESH;// 当前状态
// 初始化布局
private ImageView iv_arrow;
private ProgressBar bar_rotate;
private TextView timeTv, stateTv;
// 定义旋转动画
private RotateAnimation up, down;
// 当前是否在加载
private boolean isLoading = false;
public RefreshListView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
init();
}
private void init() {
// 设置滚动监听器
setOnScrollListener(this);
initRotateAnimation();
initHeadView();
initFootView();
}
/**
* 初始化旋转动画
* */
private void initRotateAnimation() {
// 向上旋转
up = new RotateAnimation(0, -180, RotateAnimation.RELATIVE_TO_SELF,
0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
// 动画持续的时间
up.setDuration(300);// 300ms
up.setFillAfter(true);
// 向下旋转
down = new RotateAnimation(-180, -360,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
down.setDuration(300);// 300ms
down.setFillAfter(true);
}
private void initHeadView() {
headView = View.inflate(getContext(), R.layout.head, null);
iv_arrow = (ImageView) headView.findViewById(R.id.iv_arrow);
bar_rotate = (ProgressBar) headView.findViewById(R.id.bar_rotate);
timeTv = (TextView) headView.findViewById(R.id.tv_time);
stateTv = (TextView) headView.findViewById(R.id.tv_state);
headView.measure(0, 0);
height = headView.getMeasuredHeight();
headView.setPadding(0, -height, 0, 0);
addHeaderView(headView);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
downY = (int) ev.getY();
break;
case MotionEvent.ACTION_MOVE:
int deltaY = (int) (ev.getY() - downY);
int paddingTop = -height + deltaY;
// 当课件条目是0的时候才可以下拉刷新
if (paddingTop > -height && getFirstVisiblePosition() == 0) {
headView.setPadding(0, paddingTop, 0, 0);
if (paddingTop >= 0 && currentState == PULL_REFRESH) {
// 从下拉刷新进入松开刷新状态
currentState = REALEASE_REFRESH;
refreshHeadView();
} else if (paddingTop <= 0 && currentState == REALEASE_REFRESH) {
// 进入下拉刷新状态
currentState = PULL_REFRESH;
refreshHeadView();
}
return true;// 拦截TouchMove,不然ListView处理该事件,会造成ListView无法滑动
}
break;
case MotionEvent.ACTION_UP:
if (currentState == PULL_REFRESH) {
headView.setPadding(0, -height, 0, 0);
} else if (currentState == REALEASE_REFRESH) {
// headView完全显示
headView.setPadding(0, 0, 0, 0);
currentState = REFRESHING;
refreshHeadView();
if (listener != null) {
listener.onPullRefresh();
}
}
break;
}
return super.onTouchEvent(ev);
}
/**
* 根据currentState来更新headView
*/
private void refreshHeadView() {
switch (currentState) {
case PULL_REFRESH:
stateTv.setText("下拉刷新");
iv_arrow.startAnimation(down);
break;
case REALEASE_REFRESH:
stateTv.setText("松开刷新");
iv_arrow.startAnimation(up);
break;
case REFRESHING:
// 停止动画
iv_arrow.clearAnimation();
// 隐藏箭头
iv_arrow.setVisibility(View.INVISIBLE);
// 显示bar_rotate
bar_rotate.setVisibility(View.VISIBLE);
stateTv.setText("正在刷新,请稍后");
break;
}
}
/**
* 完成刷新操作,重置状态
*/
public void completeRefresh() {
if (isLoading) {
// 重置footView
footView.setPadding(0, 0, 0, -footViewHeight);
isLoading = false;
} else {
// 重置headView
headView.setPadding(0, -height, 0, 0);
currentState = PULL_REFRESH;
bar_rotate.setVisibility(View.INVISIBLE);
iv_arrow.setVisibility(View.VISIBLE);
stateTv.setText("下拉刷新");
timeTv.setText("最后刷新:" + getCurrentTime());
}
}
/**
* 获取当前时间
*
* @return
*/
private String getCurrentTime() {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return format.format(new Date());
}
private OnRefreshListener listener;
private View footView;
private int footViewHeight;
public void setOnRefreshListener(OnRefreshListener listener) {
this.listener = listener;
}
public interface OnRefreshListener {
void onPullRefresh();
void onLoadingMore();
}
/**
* 初始化FootView
*/
private void initFootView() {
footView = View.inflate(getContext(), R.layout.bottom, null);
footView.measure(0, 0);
footViewHeight = footView.getMeasuredHeight();
// Log.e("footViewHeight","++++"+footViewHeight);
footView.setPadding(0, 0, 0, -footViewHeight);
addFooterView(footView);
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
}
/**
* SCROLL_STATE_IDLE:闲置状态,就是手指松开 SCROLL_STATE_TOUCH_SCROLL:手指触摸滚动
* SCROLL_STATE_FLING:快速手指松开
*
*/
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub
if (scrollState == OnScrollListener.SCROLL_STATE_IDLE
&& getLastVisiblePosition() == (getCount() - 1)) {
// Log.e("onScrollStateChanged","此时需要显示footView");
isLoading = true;
footView.setPadding(0, 0, 0, 0);
setSelection(getCount());// 显示ListView最后一条
if (listener != null) {
listener.onLoadingMore();
}
}
}
}
head.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="horizontal" >
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
>
<ImageView
android:id="@+id/iv_arrow"
android:layout_centerInParent="true"
android:background="@drawable/indicator_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<ProgressBar
android:id="@+id/bar_rotate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
android:layout_centerInParent="true"
android:indeterminateDuration="1000"
android:visibility="invisible"
android:indeterminateDrawable="@drawable/rotate"
/>
</RelativeLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:layout_marginLeft="15dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
>
<TextView
android:id="@+id/tv_state"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="下拉刷新"
android:textColor="#aa000000"
android:textSize="18sp"
/>
<TextView
android:id="@+id/tv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:textColor="@android:color/darker_gray"
/>
</LinearLayout>
</LinearLayout>
bottom.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal" >
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginTop="10dp"
android:indeterminate="true"
android:indeterminateDrawable="@drawable/rotate"
android:indeterminateDuration="1000" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginLeft="15dp"
android:layout_marginTop="10dp"
android:text="加载更多"
android:textColor="#aa000000"
android:textSize="20sp" />
</LinearLayout>
有需要源码的,请点击源码下载
。话不多说贴代码了
自定义的RefreshListView
package com.zyd.pullupandrefresh.view;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.zyd.pullupandrefresh.R;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ProgressBar;
import android.widget.TextView;
/**
* @author YadiZheng
*
*/
public class RefreshListView extends ListView implements OnScrollListener {
private View headView;
private int height;
private int downY;
private final int PULL_REFRESH = 0;// 下拉刷新
private final int REALEASE_REFRESH = 1;// 松开刷新
private final int REFRESHING = 2;// 正在刷新
private int currentState = PULL_REFRESH;// 当前状态
// 初始化布局
private ImageView iv_arrow;
private ProgressBar bar_rotate;
private TextView timeTv, stateTv;
// 定义旋转动画
private RotateAnimation up, down;
// 当前是否在加载
private boolean isLoading = false;
public RefreshListView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
init();
}
private void init() {
// 设置滚动监听器
setOnScrollListener(this);
initRotateAnimation();
initHeadView();
initFootView();
}
/**
* 初始化旋转动画
* */
private void initRotateAnimation() {
// 向上旋转
up = new RotateAnimation(0, -180, RotateAnimation.RELATIVE_TO_SELF,
0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
// 动画持续的时间
up.setDuration(300);// 300ms
up.setFillAfter(true);
// 向下旋转
down = new RotateAnimation(-180, -360,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
down.setDuration(300);// 300ms
down.setFillAfter(true);
}
private void initHeadView() {
headView = View.inflate(getContext(), R.layout.head, null);
iv_arrow = (ImageView) headView.findViewById(R.id.iv_arrow);
bar_rotate = (ProgressBar) headView.findViewById(R.id.bar_rotate);
timeTv = (TextView) headView.findViewById(R.id.tv_time);
stateTv = (TextView) headView.findViewById(R.id.tv_state);
headView.measure(0, 0);
height = headView.getMeasuredHeight();
headView.setPadding(0, -height, 0, 0);
addHeaderView(headView);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
downY = (int) ev.getY();
break;
case MotionEvent.ACTION_MOVE:
int deltaY = (int) (ev.getY() - downY);
int paddingTop = -height + deltaY;
// 当课件条目是0的时候才可以下拉刷新
if (paddingTop > -height && getFirstVisiblePosition() == 0) {
headView.setPadding(0, paddingTop, 0, 0);
if (paddingTop >= 0 && currentState == PULL_REFRESH) {
// 从下拉刷新进入松开刷新状态
currentState = REALEASE_REFRESH;
refreshHeadView();
} else if (paddingTop <= 0 && currentState == REALEASE_REFRESH) {
// 进入下拉刷新状态
currentState = PULL_REFRESH;
refreshHeadView();
}
return true;// 拦截TouchMove,不然ListView处理该事件,会造成ListView无法滑动
}
break;
case MotionEvent.ACTION_UP:
if (currentState == PULL_REFRESH) {
headView.setPadding(0, -height, 0, 0);
} else if (currentState == REALEASE_REFRESH) {
// headView完全显示
headView.setPadding(0, 0, 0, 0);
currentState = REFRESHING;
refreshHeadView();
if (listener != null) {
listener.onPullRefresh();
}
}
break;
}
return super.onTouchEvent(ev);
}
/**
* 根据currentState来更新headView
*/
private void refreshHeadView() {
switch (currentState) {
case PULL_REFRESH:
stateTv.setText("下拉刷新");
iv_arrow.startAnimation(down);
break;
case REALEASE_REFRESH:
stateTv.setText("松开刷新");
iv_arrow.startAnimation(up);
break;
case REFRESHING:
// 停止动画
iv_arrow.clearAnimation();
// 隐藏箭头
iv_arrow.setVisibility(View.INVISIBLE);
// 显示bar_rotate
bar_rotate.setVisibility(View.VISIBLE);
stateTv.setText("正在刷新,请稍后");
break;
}
}
/**
* 完成刷新操作,重置状态
*/
public void completeRefresh() {
if (isLoading) {
// 重置footView
footView.setPadding(0, 0, 0, -footViewHeight);
isLoading = false;
} else {
// 重置headView
headView.setPadding(0, -height, 0, 0);
currentState = PULL_REFRESH;
bar_rotate.setVisibility(View.INVISIBLE);
iv_arrow.setVisibility(View.VISIBLE);
stateTv.setText("下拉刷新");
timeTv.setText("最后刷新:" + getCurrentTime());
}
}
/**
* 获取当前时间
*
* @return
*/
private String getCurrentTime() {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return format.format(new Date());
}
private OnRefreshListener listener;
private View footView;
private int footViewHeight;
public void setOnRefreshListener(OnRefreshListener listener) {
this.listener = listener;
}
public interface OnRefreshListener {
void onPullRefresh();
void onLoadingMore();
}
/**
* 初始化FootView
*/
private void initFootView() {
footView = View.inflate(getContext(), R.layout.bottom, null);
footView.measure(0, 0);
footViewHeight = footView.getMeasuredHeight();
// Log.e("footViewHeight","++++"+footViewHeight);
footView.setPadding(0, 0, 0, -footViewHeight);
addFooterView(footView);
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
}
/**
* SCROLL_STATE_IDLE:闲置状态,就是手指松开 SCROLL_STATE_TOUCH_SCROLL:手指触摸滚动
* SCROLL_STATE_FLING:快速手指松开
*
*/
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub
if (scrollState == OnScrollListener.SCROLL_STATE_IDLE
&& getLastVisiblePosition() == (getCount() - 1)) {
// Log.e("onScrollStateChanged","此时需要显示footView");
isLoading = true;
footView.setPadding(0, 0, 0, 0);
setSelection(getCount());// 显示ListView最后一条
if (listener != null) {
listener.onLoadingMore();
}
}
}
}
head.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="horizontal" >
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
>
<ImageView
android:id="@+id/iv_arrow"
android:layout_centerInParent="true"
android:background="@drawable/indicator_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<ProgressBar
android:id="@+id/bar_rotate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
android:layout_centerInParent="true"
android:indeterminateDuration="1000"
android:visibility="invisible"
android:indeterminateDrawable="@drawable/rotate"
/>
</RelativeLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:layout_marginLeft="15dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
>
<TextView
android:id="@+id/tv_state"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="下拉刷新"
android:textColor="#aa000000"
android:textSize="18sp"
/>
<TextView
android:id="@+id/tv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:textColor="@android:color/darker_gray"
/>
</LinearLayout>
</LinearLayout>
bottom.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal" >
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginTop="10dp"
android:indeterminate="true"
android:indeterminateDrawable="@drawable/rotate"
android:indeterminateDuration="1000" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginLeft="15dp"
android:layout_marginTop="10dp"
android:text="加载更多"
android:textColor="#aa000000"
android:textSize="20sp" />
</LinearLayout>
有需要源码的,请点击源码下载
相关文章推荐
- Android 讲解:存储 (1)
- Android应用开发基础篇(1)-----Button
- Android中通过拨号调起应用的实现方式及特殊情况处理
- android:强大的图片下载和缓存库Picasso
- Android显示gif
- Android开发之EditText 详解(addTextChangedListener监听用户输入状态)
- 实现android知乎、一览等的开场动画图片放大效果
- android-如何通过接口回调来解决Fragment之间的交互
- 一张图搞定Android学习路线,非常全面
- android开发使用SDK与ANT实现自动打包(混淆、签名)
- android:View的setTag和getTag使用
- android anr trace.txt文件 抓取
- Yalantis 那些动画效果很炫的 Android 及 iOS 开源项目
- android - 自定义(组合)控件 + 自定义控件外观
- Android系统源码学习步骤
- android:layout_marginStart和android:paddingStart的区别
- 提升Android开发效率的5个经验总结【同行说技术】
- Android开发笔记(五十一)通过Messenger实现进程间通信
- Android百分比布局
- Android 常用六大框架