package com.duguang.baseanimation.ui.listivew.refresh.view;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.duguang.baseanimation.R;
import com.duguang.baseanimation.ui.listivew.refresh.interf.OnRefreshListener;
public class RefreshListView extends ListView implements OnScrollListener {
private int downY; // 按下时y轴的偏移量
private View headerView; // 头布局
private int headerViewHeight; // 头布局的高度
private int firstVisibleItemPosition; // 滚动时界面显示在顶部的item的position
private DisplayMode currentState = DisplayMode.Pull_Down; // 头布局当前的状态, 缺省值为下拉状态
private Animation upAnim; // 向上旋转的动画
private Animation downAnim; // 向下旋转的动画
private ImageView ivArrow; // 头布局的箭头
private TextView tvState; // 头布局刷新状态
private ProgressBar mProgressBar; // 头布局的进度条
private TextView tvLastUpdateTime; // 头布局的最后刷新时间
private OnRefreshListener mOnRefreshListener;
private boolean isScroll2Bottom = false; // 是否滚动到底部
private View footerView; // 脚布局
private int footerViewHeight; // 脚布局的高度
private boolean isLoadMoving = false; // 是否正在加载更多中
public RefreshListView(Context context, AttributeSet attrs) {
super(context, attrs);
initHeader();
initFooter();
this.setOnScrollListener(this);
}
/**
* 初始化脚布局
*/
private void initFooter() {
footerView = LayoutInflater.from(getContext()).inflate(R.layout.activity_listview_refresh_footer, null);
measureView(footerView); // 测量一下脚布局的高度
footerViewHeight = footerView.getMeasuredHeight();
footerView.setPadding(0, -footerViewHeight, 0, 0); // 隐藏脚布局
this.addFooterView(footerView);
}
/**
* 初始化头布局
*/
private void initHeader() {
headerView = LayoutInflater.from(getContext()).inflate(R.layout.activity_listview_refresh_header, null);
ivArrow = (ImageView) headerView.findViewById(R.id.iv_listview_header_down_arrow);
mProgressBar = (ProgressBar) headerView.findViewById(R.id.pb_listview_header_progress);
tvState = (TextView) headerView.findViewById(R.id.tv_listview_header_state);
tvLastUpdateTime = (TextView) headerView.findViewById(R.id.tv_listview_header_last_update_time);
ivArrow.setMinimumWidth(50);
tvLastUpdateTime.setText("最后刷新时间: " + getLastUpdateTime());
measureView(headerView);
headerViewHeight = headerView.getMeasuredHeight();
Log.i("RefreshListView", "头布局的高度: " + headerViewHeight);
headerView.setPadding(0, -headerViewHeight, 0, 0);
this.addHeaderView(headerView);
initAnimation();
}
/**
* 获得最后刷新的时间
* @return
*/
private String getLastUpdateTime() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(new Date());
}
/**
* 初始化动画
*/
private void initAnimation() {
upAnim = new RotateAnimation(
0, -180,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
upAnim.setDuration(500);
upAnim.setFillAfter(true);
downAnim = new RotateAnimation(
-180, -360,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
downAnim.setDuration(500);
downAnim.setFillAfter(true);
}
/**
* 测量给定的View的宽和高, 测量之后, 可以得到view的宽和高
* @param child
*/
private void measureView(View child) {
ViewGroup.LayoutParams lp = child.getLayoutParams();
if (lp == null) {
lp = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
}
int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0, lp.width);
int lpHeight = lp.height;
int childHeightSpec;
if (lpHeight > 0) {
childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
} else {
childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
}
child.measure(childWidthSpec, childHeightSpec);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
downY = (int) ev.getY();
break;
case MotionEvent.ACTION_MOVE:
if(currentState == DisplayMode.Refreshing) {
// 当前的状态是正在刷新中, 不执行下拉操作
break;
}
int moveY = (int) ev.getY(); // 移动中的y轴的偏移量
int diffY = moveY - downY;
int paddingTop = -headerViewHeight + (diffY / 2);
if(firstVisibleItemPosition == 0
&& paddingTop > -headerViewHeight) {
/**
* paddingTop > 0 完全显示
* currentState == DisplayMode.Pull_Down 当是在下拉状态时
*/
if(paddingTop > 0 // 完全显示
&& currentState == DisplayMode.Pull_Down) { // 完全显示, 进入到刷新状态
Log.i("RefreshListView", "松开刷新");
currentState = DisplayMode.Release_Refresh; // 把当前的状态改为松开刷新
refreshHeaderViewState();
} else if(paddingTop < 0
&& currentState == DisplayMode.Release_Refresh) { // 没有完全显示, 进入到下拉状态
Log.i("RefreshListView", "下拉刷新");
currentState = DisplayMode.Pull_Down;
refreshHeaderViewState();
}
headerView.setPadding(0, paddingTop, 0, 0);
return true;
}
break;
case MotionEvent.ACTION_UP:
downY = -1;
if(currentState == DisplayMode.Pull_Down) { // 松开时, 当前显示的状态为下拉状态, 执行隐藏headerView的操作
headerView.setPadding(0, -headerViewHeight, 0, 0);
} else if(currentState == DisplayMode.Release_Refresh) { // 松开时, 当前显示的状态为松开刷新状态, 执行刷新的操作
headerView.setPadding(0, 0, 0, 0);
currentState = DisplayMode.Refreshing;
refreshHeaderViewState();
if(mOnRefreshListener != null) {
mOnRefreshListener.onRefresh();
}
}
break;
default:
break;
}
return super.onTouchEvent(ev);
}
/**
* 当刷新任务执行完毕时, 回调此方法, 去刷新界面
*/
public void onRefreshFinish() {
if(isLoadMoving) { // 隐藏脚布局
isLoadMoving = false;
isScroll2Bottom = false;
footerView.setPadding(0, -footerViewHeight, 0, 0);
} else { // 隐藏头布局
headerView.setPadding(0, -headerViewHeight, 0, 0);
mProgressBar.setVisibility(View.GONE);
ivArrow.setVisibility(View.VISIBLE);
tvLastUpdateTime.setText("最后刷新时间: " + getLastUpdateTime());
currentState = DisplayMode.Pull_Down;
}
}
/**
* 刷新头布局的状态
*/
private void refreshHeaderViewState() {
if(currentState == DisplayMode.Pull_Down) { // 当前进入下拉状态
ivArrow.startAnimation(downAnim);
tvState.setText("下拉刷新");
} else if(currentState == DisplayMode.Release_Refresh) { //当前进入松开刷新状态
ivArrow.startAnimation(upAnim);
tvState.setText("松开刷新");
} else if(currentState == DisplayMode.Refreshing) { //当前进入正在刷新中
ivArrow.clearAnimation();
ivArrow.setVisibility(View.GONE);
mProgressBar.setVisibility(View.VISIBLE);
tvState.setText("正在刷新中..");
}
}
/**
* 当ListView滚动状态改变时回调
* SCROLL_STATE_IDLE // 当ListView滚动停止时
* SCROLL_STATE_TOUCH_SCROLL // 当ListView触摸滚动时
* SCROLL_STATE_FLING // 快速的滚动(手指快速的触摸移动)
*/
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if(scrollState == OnScrollListener.SCROLL_STATE_IDLE
|| scrollState == OnScrollListener.SCROLL_STATE_FLING) {
if(isScroll2Bottom && !isLoadMoving) { // 滚动到底部
// 加载更多
footerView.setPadding(0, 0, 0, 0);
this.setSelection(this.getCount()); // 滚动到ListView的底部
isLoadMoving = true;
if(mOnRefreshListener != null) {
mOnRefreshListener.onLoadMoring();
}
}
}
}
/**
* 当ListView滚动时触发
* firstVisibleItem 屏幕上显示的第一个Item的position
* visibleItemCount 当前屏幕显示的总个数
* totalItemCount ListView的总条数
*/
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
firstVisibleItemPosition = firstVisibleItem;
Log.i("RefreshListView", "onScroll: " + firstVisibleItem + ", " + visibleItemCount + ", " + totalItemCount);
if((firstVisibleItem + visibleItemCount) >= totalItemCount
&& totalItemCount > 0) {
// Log.i("RefreshListView", "加载更多");
isScroll2Bottom = true;
} else {
isScroll2Bottom = false;
}
}
/**
* @author andong
* 下拉头部的几种显示状态
*/
public enum DisplayMode {
Pull_Down, // 下拉刷新的状态
Release_Refresh, // 松开刷新的状态
Refreshing // 正在刷新中的状态
}
/**
* 设置刷新的监听事件
* @param listener
*/
public void setOnRefreshListener(OnRefreshListener listener) {
this.mOnRefreshListener = listener;
}
}