import java.text.SimpleDateFormat;
import java.util.Date;
import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
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.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.study.smartservice.R;
@SuppressLint("SimpleDateFormat")
public class RefreshListView extends ListView implements OnScrollListener {
private LinearLayout refresh_listview_header_root;
private LinearLayout refresh_listview_header_view;
private ImageView refresh_listview_header_image;
private ProgressBar refresh_listview_header_progress;
private TextView refresh_listview_header_text;
private TextView refresh_listview_header_date;
private RotateAnimation animationUp;
private RotateAnimation animationDown;
private View customView;
private int headerHeight;
// 下拉刷新
private static final int PULL_REFRESH = 1;
// 释放刷新
private static final int RELEASE_REFRESH = 2;
// 正在刷新
private static final int IS_REFRESHING = 3;
private static final String tag = "RefreshListView";
private static int CURRENTOPTION = PULL_REFRESH;
private OnRefreshListener onRefreshListener;
// 模拟请求网络的逻辑
// private Handler handler = new Handler() {
// public void handleMessage(android.os.Message msg) {
// onRefreshFinish();
// };
// };
public RefreshListView(Context context) {
super(context);
initHeader();
initFooter();
setOnScrollListener(this);
}
public RefreshListView(Context context, AttributeSet attrs) {
super(context, attrs);
initHeader();
initFooter();
setOnScrollListener(this);
}
// 初始化头布局
private void initHeader() {
// 总布局:包含刷新头,ViewPager,该布局要加入ListView当做listView的头布局
View viewHeader = View.inflate(getContext(),
R.layout.refresh_listview_header, null);
// 刷新头布局:包含ViewPager,在下面会提供一个方法,将viewPager的view添加到此布局的下方
refresh_listview_header_root = (LinearLayout) viewHeader
.findViewById(R.id.refresh_listview_header_root);
// 刷新头布局:不包含ViewPager
refresh_listview_header_view = (LinearLayout) viewHeader
.findViewById(R.id.refresh_listview_header_view);
// 刷新头图片
refresh_listview_header_image = (ImageView) viewHeader
.findViewById(R.id.refresh_listview_header_image);
// 刷新头ProgressBar
refresh_listview_header_progress = (ProgressBar) viewHeader
.findViewById(R.id.refresh_listview_header_progress);
// 刷新头文字
refresh_listview_header_text = (TextView) viewHeader
.findViewById(R.id.refresh_listview_header_text);
// 刷新头时间
refresh_listview_header_date = (TextView) viewHeader
.findViewById(R.id.refresh_listview_header_date);
// 一开始刷新头不能出现,因此计算刷新头对应的高度
refresh_listview_header_view.measure(0, 0);
// 获取测量后的高度
headerHeight = refresh_listview_header_view.getMeasuredHeight();
// 相当于隐藏了刷新头
refresh_listview_header_view.setPadding(0, -headerHeight, 0, 0);
// 给当前listView添加一个头布局,即将包含刷新头和ViewPager的布局加入ListView头部
this.addHeaderView(viewHeader);
// 初始化动画
initAnimation();
}
// 初始化底部布局
private void initFooter() {
View viewFooter = View.inflate(getContext(),
R.layout.refresh_listview_footer, null);
refresh_listview_footer_foot = (LinearLayout) viewFooter
.findViewById(R.id.refresh_listview_footer_foot);
refresh_listview_footer_foot.measure(0, 0);
footerdHeight = refresh_listview_footer_foot.getMeasuredHeight();
refresh_listview_footer_foot.setPadding(0, -footerdHeight, 0, 0);
// 给当前listView添加一个底部布局,即将包含刷新底部布局加入此ListView
this.addFooterView(viewFooter);
}
private void initAnimation() {
// 把图片朝上动画
animationUp = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF,
0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
// 旋转时间
animationUp.setDuration(500);
// 旋转过后保持位置
animationUp.setFillAfter(true);
// 把图片朝下动画
animationDown = new RotateAnimation(-180, -360,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
0.5f);
// 旋转时间
animationDown.setDuration(500);
// 旋转过后保持位置
animationDown.setFillAfter(true);
}
/**
* 下拉和上拉的两个接口
*
* @author TCL
*/
public interface OnRefreshListener {
public void pullDownRefresh();
public void pullUpLoad();
}
public void onRefreshFinish() {
// 下拉刷新完毕的方法
if (CURRENTOPTION == IS_REFRESHING) {
CURRENTOPTION = PULL_REFRESH;
refresh_listview_header_progress.setVisibility(View.INVISIBLE);
refresh_listview_header_text.setText("下拉刷新");
refresh_listview_header_image.setVisibility(View.VISIBLE);
refresh_listview_header_view.setPadding(0, -headerHeight, 0, 0);
}
if (isLoading) {
isLoading = false;
refresh_listview_footer_foot.setPadding(0, -footerdHeight, 0, 0);
}
}
public void setOnRefreshListener(OnRefreshListener onRefreshListener) {
this.onRefreshListener = onRefreshListener;
}
// 监听手势的事件
private int downY = -1;
private int firstVisibleItem = -1;
private LinearLayout refresh_listview_footer_foot;
private int footerdHeight;
private boolean isLoading;
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
downY = (int) ev.getY();
break;
case MotionEvent.ACTION_MOVE:
if (downY == -1) {
downY = (int) ev.getY();
}
int moveY = (int) ev.getY();
// 正在刷新的时候不让ListView拖动
if (CURRENTOPTION == IS_REFRESHING) {
break;
}
// 获取ListView所在屏幕上左上角坐标
int[] listViewLocation = new int[2];
// 给数组赋值
this.getLocationOnScreen(listViewLocation);
// 获取当前ListView对应的Y值
int listViewY = listViewLocation[1];
// 获取轮播图在屏幕左上角的坐标
int[] customViewLoction = new int[2];
customView.getLocationOnScreen(customViewLoction);
int customViewY = customViewLoction[1];
if (listViewY > customViewY) {
break;
}
int padding = -headerHeight + moveY - downY;
// moveY-downY>0,此时向下拉,并且当前的第一个条目是索引中的第一个
if (padding > -headerHeight && firstVisibleItem == 0) {
// 响应下拉刷新头展示的操作
if (padding > 0 && CURRENTOPTION == PULL_REFRESH) {
// 此时已经完整的吧刷新头拉出来了并且当前状态是下拉刷新
CURRENTOPTION = RELEASE_REFRESH;
setCurrentOpiton();
Log.i(tag, "释放刷新");
}
if (padding < 0 && CURRENTOPTION == RELEASE_REFRESH) {
// 刷新头一部分显示,一部分隐藏
CURRENTOPTION = PULL_REFRESH;
setCurrentOpiton();
Log.i(tag, "下拉刷新");
}
refresh_listview_header_view.setPadding(0, padding, 0, 0);
// 保证手放开的时候去响应up事件
return true;
}
break;
case MotionEvent.ACTION_UP:
if (CURRENTOPTION == RELEASE_REFRESH) {
CURRENTOPTION = IS_REFRESHING;
// 刷新
setCurrentOpiton();
// 结合逻辑去做刷新操作(回调)
if (onRefreshListener != null) {
onRefreshListener.pullDownRefresh();
}
// handler.sendEmptyMessageDelayed(0, 2000);
refresh_listview_header_view.setPadding(0, 0, 0, 0);
} else if (CURRENTOPTION == PULL_REFRESH) {
// 做一个弹回的操作
refresh_listview_header_view.setPadding(0, -headerHeight, 0, 0);
}
break;
}
return super.onTouchEvent(ev);
}
/**
* 处理状态的方法
*/
public void setCurrentOpiton() {
switch (CURRENTOPTION) {
case RELEASE_REFRESH:
refresh_listview_header_text.setText("释放刷新");
refresh_listview_header_image.startAnimation(animationUp);
break;
case PULL_REFRESH:
refresh_listview_header_text.setText("下拉刷新");
refresh_listview_header_image.startAnimation(animationDown);
break;
case IS_REFRESHING:
refresh_listview_header_text.setText("正在刷新");
refresh_listview_header_image.clearAnimation();
refresh_listview_header_image.setVisibility(View.GONE);
refresh_listview_header_progress.setVisibility(View.VISIBLE);
refresh_listview_header_date.setText(getTime());
}
}
private String getTime() {
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss");
return dateFormat.format(date);
}
// 提供一个方法将轮播图对应的view放置进来
public void addCustomView(View v) {
customView = v;
// 因为该布局中已有一个刷新头,所以再添加的view在刷新头下方
refresh_listview_header_root.addView(customView);
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// 监听ListView滚动状态发生改变的方法
if (scrollState == OnScrollListener.SCROLL_STATE_FLING
|| scrollState == OnScrollListener.SCROLL_STATE_IDLE) {
// 当前最后一个可见条目
if (getLastVisiblePosition() == getAdapter().getCount() - 1
&& !isLoading) {
// 加载更多操作
isLoading = true;
refresh_listview_footer_foot.setPadding(0, 0, 0, 0);
// 加载更多的逻辑(回调)
if (onRefreshListener != null) {
onRefreshListener.pullUpLoad();
}
// handler.sendEmptyMessageDelayed(0, 2000);
}
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// 当前滚动操作的头对应索引
this.firstVisibleItem = firstVisibleItem;
}
}
refresh_listview_header.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/refresh_listview_header_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<!-- 刷新头 -->
<LinearLayout
android:id="@+id/refresh_listview_header_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<!-- 左侧图片 -->
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp" >
<ImageView
android:id="@+id/refresh_listview_header_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/common_listview_headview_red_arrow" />
<ProgressBar
android:id="@+id/refresh_listview_header_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible" />
</FrameLayout>
<!-- 刷新文字 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="center"
android:gravity="center">
<TextView
android:id="@+id/refresh_listview_header_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="下拉刷新" />
<TextView
android:id="@+id/refresh_listview_header_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1999-10-10" />
</LinearLayout>
</LinearLayout>
<!-- 在此添加轮播图 -->
</LinearLayout>
refresh_listview_footer.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/refresh_listview_footer_foot"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:layout_gravity="center"
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="正在加载"
android:textSize="20sp"/>
</LinearLayout>