1.activity
package com.example.refreshlistview;
import java.util.ArrayList;
import com.example.refreshlistview.view.refreshListView;
import com.example.refreshlistview.view.refreshListView.isRefreshListener;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.BaseAdapter;
import android.widget.TextClock;
import android.widget.TextView;
public class MainActivity extends Activity {
private ArrayList<String> dataList;
private refreshListView rlv;
private String tag="MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
initUI();
initData();
initAdapter();
}
/**
* 初始化适配器
*/
private void initAdapter() {
final myAdapter myAdapter = new myAdapter();
rlv.setAdapter(myAdapter);
rlv.setOnIsRefreshListener(new isRefreshListener() {
@Override
public void headRefresh() {
new Thread() {
public void run() {
try {
sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
dataList.add(0, "添加头部数据");
runOnUiThread(new Runnable() {
public void run() {
myAdapter.notifyDataSetChanged();
rlv.closeHead();
}
});
};
}.start();
}
@Override
public void footLoading() {
new Thread() {
public void run() {
try {
sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
dataList.add(dataList.size(), "添加脚步数据");
runOnUiThread(new Runnable() {
public void run() {
myAdapter.notifyDataSetChanged();
rlv.closeFoot();
}
});
};
}.start();
}
});
}
/**
* 初始化数据
*/
private void initData() {
dataList = new ArrayList<String>();
for (int i = 0; i < 40; i++) {
dataList.add("这是数据:" + i);
}
}
/**
* 找到控件
*/
private void initUI() {
rlv = (refreshListView) findViewById(R.id.rlv);
}
class myAdapter extends BaseAdapter {
@Override
public int getCount() {
return dataList.size();
}
@Override
public String getItem(int position) {
// TODO Auto-generated method stub
return dataList.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView textView = new TextView(getApplicationContext());
textView.setText(getItem(position));
textView.setTextColor(Color.BLACK);
textView.setTextSize(18);
textView.setPadding(5, 5, 5, 5);
convertView = textView;
return convertView;
}
}
}
2.布局控件
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${relativePackage}.${activityClass}" >
<com.example.refreshlistview.view.refreshListView
android:id="@+id/rlv"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
item_diy_list_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="wrap_content"
android:orientation="horizontal" >
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:gravity="center"
android:padding="5dp" >
<ImageView
android:id="@+id/iv_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/common_listview_headview_red_arrow" />
<ProgressBar
android:id="@+id/pb_ring"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminateDrawable="@drawable/shape_pb" />
</RelativeLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:gravity="center"
android:orientation="vertical" >
<TextView
android:id="@+id/tv_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="下拉刷新"
android:textColor="#f22"
android:textSize="26sp" />
<TextView
android:id="@+id/tv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="最后刷新时间:2018-7-26 09:16:55" />
</LinearLayout>
</LinearLayout>
item_diy_list_foot.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:indeterminateDrawable="@drawable/shape_pb" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="加载更多..."
android:textColor="#f22"
android:textSize="26sp" />
</LinearLayout>
3.自定义控件
package com.example.refreshlistview.view;
import java.security.acl.LastOwnerException;
import java.text.SimpleDateFormat;
import javax.crypto.spec.IvParameterSpec;
import com.example.refreshlistview.R;
import android.content.Context;
import android.content.pm.FeatureInfo;
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.ImageView;
import android.widget.ListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ProgressBar;
import android.widget.TextView;
public class refreshListView extends ListView implements OnScrollListener {
private String tag = "refreshListView";
private RotateAnimation mArrowToUp;
private RotateAnimation mArrowToDown;
private View mHead_view;
private int mHeadMeasuredHeight;
public static final int DOWN_TO_REFRESH = 100;
public static final int FREE_TO_REFRESH = 101;
public static final int IS_REFRESH = 102;
public static final boolean IS_LOADING = true;
public static final boolean UNLOADING = false;
private boolean foot_state = UNLOADING;
private int head_state = DOWN_TO_REFRESH;
private float downY;
private float moveY;
private int paddingTop;
private ImageView mIv_arrow;
private ProgressBar mPb_ring;
private TextView mTv_desc;
private TextView mTv_time;
private isRefreshListener irl;
private View mFoot_view;
private int mFootMeasuredHeight;
public refreshListView(Context context) {
super(context);
init();
}
public refreshListView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public refreshListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
/**
* 初始化
*/
private void init() {
initUI();
initHead();
initFoot();
initAnimation();
}
/**
* 初始化脚部控件
*/
private void initFoot() {
mFootMeasuredHeight = mFoot_view.getMeasuredHeight();
// 设置padding
mFoot_view.setPadding(0, -mFootMeasuredHeight, 0, 0);
// 把控件加入listview
addFooterView(mFoot_view);
}
/**
* 找到控件
*/
private void initUI() {
// 得到控件
mHead_view = View.inflate(getContext(), R.layout.item_diy_list_head,
null);
mFoot_view = View.inflate(getContext(), R.layout.item_diy_list_foot,
null);
mHead_view.measure(0, 0);
mFoot_view.measure(0, 0);
mIv_arrow = (ImageView) mHead_view.findViewById(R.id.iv_arrow);
mPb_ring = (ProgressBar) mHead_view.findViewById(R.id.pb_ring);
mTv_desc = (TextView) mHead_view.findViewById(R.id.tv_desc);
mTv_time = (TextView) mHead_view.findViewById(R.id.tv_time);
// 设置进度条不可见
mPb_ring.setVisibility(View.INVISIBLE);
setOnScrollListener(this);
}
/**
* 初始化动画
*/
private void initAnimation() {
// 箭头向上指的动画
mArrowToUp = new RotateAnimation(0f, -180f, Animation.RELATIVE_TO_SELF,
0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
mArrowToUp.setFillAfter(true);
mArrowToUp.setDuration(100);
// 箭头向下指的动画
mArrowToDown = new RotateAnimation(-180f, -360f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
0.5f);
mArrowToDown.setFillAfter(true);
mArrowToDown.setDuration(100);
}
/**
* 初始化头部
*/
private void initHead() {
mHeadMeasuredHeight = mHead_view.getMeasuredHeight();
// 设置padding
mHead_view.setPadding(0, -mHeadMeasuredHeight, 0, 0);
// 把控件加入listview
addHeaderView(mHead_view);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
downY = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
if (head_state == IS_REFRESH) {
return super.onTouchEvent(ev);
}
moveY = ev.getY();
// 得到移动距离
float moveLength = moveY - downY;
paddingTop = (int) (-mHeadMeasuredHeight + moveLength);
// 当第一行可见控件是第一个listview条目时运行下面的代码
if (getFirstVisiblePosition() == 0) {
if (paddingTop >= mHeadMeasuredHeight
&& head_state != FREE_TO_REFRESH) {
// 状态变为松开刷新
head_state = FREE_TO_REFRESH;
updateHeadView();
} else if (paddingTop < mHeadMeasuredHeight
&& head_state != DOWN_TO_REFRESH) {
// 状态变为下拉刷新
head_state = DOWN_TO_REFRESH;
updateHeadView();
}
}
mHead_view.setPadding(0, paddingTop, 0, 0);
break;
case MotionEvent.ACTION_UP:
if (head_state == IS_REFRESH) {
return super.onTouchEvent(ev);
}
if (head_state == FREE_TO_REFRESH) {
head_state = IS_REFRESH;
updateHeadView();
} else {
closeHead();
}
break;
default:
break;
}
return super.onTouchEvent(ev);
}
private void updateHeadView() {
if (foot_state == IS_LOADING) {
//显示脚部控件
mFoot_view.setPadding(0, 0, 0, 0);
if (irl != null) {
irl.footLoading();
}
} else {
switch (head_state) {
// 松开刷新状态
case FREE_TO_REFRESH:
mTv_desc.setText("松开刷新");
mIv_arrow.startAnimation(mArrowToUp);
break;
// 下拉刷新状态
case DOWN_TO_REFRESH:
mTv_desc.setText("下拉刷新");
mIv_arrow.startAnimation(mArrowToDown);
break;
// 刷新状态
case IS_REFRESH:
mTv_desc.setText("正在刷新...");
mIv_arrow.clearAnimation();
mIv_arrow.setVisibility(View.GONE);
mPb_ring.setVisibility(View.VISIBLE);
mHead_view.setPadding(0, 0, 0, 0);
if (irl != null) {
irl.headRefresh();
}
break;
default:
break;
}
}
}
/**
* 初始化头部控件
*/
public void closeHead() {
// 状态回归
head_state = DOWN_TO_REFRESH;
mTv_desc.setText("下拉刷新");
// 回归原位
mHead_view.setPadding(0, -mHeadMeasuredHeight, 0, 0);
// 初始化箭头和进度条
mIv_arrow.setVisibility(View.VISIBLE);
mPb_ring.setVisibility(View.GONE);
mTv_time.setText("最后刷新时间:" + getTime());
}
/**
* 初始化底部
*/
public void closeFoot() {
Log.d(tag, "初始化底部");
// 状态回归
foot_state = UNLOADING;
// 回归原位
mFoot_view.setPadding(0, -mFootMeasuredHeight, 0, 0);
// 初始化箭头和进度条
}
public interface isRefreshListener {
public abstract void headRefresh();
public abstract void footLoading();
}
public void setOnIsRefreshListener(isRefreshListener irl) {
this.irl = irl;
}
private String getTime() {
long timeMillis = System.currentTimeMillis();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss");
return simpleDateFormat.format(timeMillis);
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (foot_state == IS_LOADING) {
return;
}
switch (scrollState) {
case OnScrollListener.SCROLL_STATE_IDLE:
if (getLastVisiblePosition() >= getCount()-1) {
foot_state = IS_LOADING;
updateHeadView();
}
break;
case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
break;
case OnScrollListener.SCROLL_STATE_FLING:
break;
default:
break;
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
}
}