您的位置:首页 > 移动开发 > Android开发

Android 自定义下拉刷新上拉加载更多Listview

2015-10-12 21:37 656 查看
好久没写了。。先说一下这边隐藏头部布局的原理:

//将padding设置为header的高度的负值来隐藏它
footerView.setPadding(0, -footerViewH, 0, 0);



先是预备工作:上拉加载更多底部布局

<?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_marginTop="10dp"
android:layout_marginBottom="10dp"
android:indeterminate="true"
android:layout_centerInParent="true"
android:indeterminateDrawable="@drawable/indeterminate_drawable"
android:indeterminateDuration="500"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:textSize="30dp"
android:layout_marginLeft="15dp"
android:text="正在加载更多..."/>
</LinearLayout>
下拉刷新头部布局:

<?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_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_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/indicator_arrow" />
<ProgressBar
android:id="@+id/pb_ratate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible"
android:indeterminate="true"
android:layout_centerInParent="true"
android:indeterminateDrawable="@drawable/indeterminate_drawable"
android:indeterminateDuration="500"
/>
</RelativeLayout>

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:orientation="vertical"
android:layout_gravity="center"
android:gravity="center">
<TextView
android:id="@+id/tv_state"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp"
android:textColor="#aa000000"
android:text="下拉刷新"
/>
<TextView
android:id="@+id/tv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18dp"
android:textColor="#99666666"
android:text="最后刷新:2015-12-03"
/>
</LinearLayout>
</LinearLayout>


然后就是自定义RefreshListview!

注释很详细,大家慢慢看一下:

public class RefreshListView extends ListView implements AbsListView.OnScrollListener {
private View headView;
private ImageView iv_arrow;//箭头图标
private ProgressBar pb_ratate;//刷新中图标
private TextView tv_state;//刷新状态文本
private TextView tv_time;//最新刷新时间
private View footerView;

private int headViewH;
private int footerViewH;
//触摸点Y的坐标
private int downY;

private final int PULL_REFRESH = 0;//下拉刷新的状态
private final int RELEASE_REFRESH = 1;//松开刷新的状态
private final int REFRESHING = 2;//正在刷新状态
private int currentState = PULL_REFRESH;//当前状态,默认为下拉刷新状态
private boolean isLoadingMore = false;//是否加载更多

private RotateAnimation upAnimation;
private RotateAnimation downAnimation;

public RefreshListView(Context context) {
super(context);
init();
}

public RefreshListView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}

private void init() {
setOnScrollListener(this);
initHeaderView();
initRotateAnimation();
initFooterView();
}

/**
* 初始化headerview
*/
private void initHeaderView() {

headView = View.inflate(getContext(), R.layout.layout_header, null);
iv_arrow = (ImageView) headView.findViewById(R.id.iv_arrow);
pb_ratate = (ProgressBar) headView.findViewById(R.id.pb_ratate);
tv_state = (TextView) headView.findViewById(R.id.tv_state);
tv_time = (TextView) headView.findViewById(R.id.tv_time);
//通知系统主动去测量
headView.measure(0, 0);
//getMeasuredHeight()获取测量后的高度

headViewH = headView.getMeasuredHeight();
//将padding设置为header的高度的负值来隐藏它
headView.setPadding(0, -headViewH, 0, 0);
addHeaderView(headView);
}

private void initRotateAnimation() {
upAnimation = new RotateAnimation(0, -180,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
upAnimation.setDuration(300);
upAnimation.setFillAfter(true);
downAnimation = new RotateAnimation(-180, -360,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
downAnimation.setDuration(300);
downAnimation.setFillAfter(true);
}

/**
* 初始化FooterView
*/
private void initFooterView() {
footerView = View.inflate(getContext(), R.layout.layout_footer, null);
//通知系统主动去测量
footerView.measure(0, 0);
//getMeasuredHeight()获取测量后的高度
footerViewH = footerView.getMeasuredHeight();
//将padding设置为header的高度的负值来隐藏它
footerView.setPadding(0, -footerViewH, 0, 0);
addFooterView(footerView);
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
downY = (int) ev.getY();
break;
case MotionEvent.ACTION_MOVE:
if (currentState == REFRESHING) {
break;
}
int delaY = (int) (ev.getY() - downY);
//距离顶部的大小
int paddingTop = -headViewH + delaY;
//只有当paddingTop> -headViewH,且第一项为首项时才进行拦截
if (paddingTop > -headViewH && getFirstVisiblePosition() == 0) {
headView.setPadding(0, paddingTop, 0, 0);
if (paddingTop >= 0 && currentState == PULL_REFRESH) {
//从下拉刷新进去松开刷新状态
currentState = RELEASE_REFRESH;
refreshHeadView();
} else if (paddingTop < 0 && currentState == RELEASE_REFRESH) {
//进去下拉刷新状态
currentState = PULL_REFRESH;
refreshHeadView();
}
return true;//拦截TOUCH_MOVE,不让listview处理move事件
}
break;
case MotionEvent.ACTION_UP:
if (currentState == PULL_REFRESH) {
headView.setPadding(0, -headViewH, 0, 0);
} else if (currentState == RELEASE_REFRESH) {
headView.setPadding(0, 0, 0, 0);
currentState = REFRESHING;
refreshHeadView();
if (onRefreshListener != null) {
onRefreshListener.onPullRefresh();
}
}
break;
}
return super.onTouchEvent(ev);
}

/**
* 根据currentState改变headview
*/
private void refreshHeadView() {
switch (currentState) {
case PULL_REFRESH:
tv_state.setText("下拉刷新");
iv_arrow.startAnimation(downAnimation);
break;
case RELEASE_REFRESH:
tv_state.setText("松开刷新");
iv_arrow.startAnimation(upAnimation);
break;
case REFRESHING:
tv_state.setText("正在拼命加载中...");
iv_arrow.clearAnimation();//因为向上旋转的动画有可能还未完成
iv_arrow.setVisibility(View.INVISIBLE);
pb_ratate.setVisibility(VISIBLE);
break;
}
}

/**
* 完成刷新,重置状态,在获取完数据并更新完adapter之后,在UI线程中调用
*/
public void completeRefresh() {
if (isLoadingMore){
footerView.setPadding(0,0,0,-footerViewH);
isLoadingMore=false;
}else {
headView.setPadding(0, -headViewH, 0, 0);
currentState = PULL_REFRESH;
pb_ratate.setVisibility(INVISIBLE);
iv_arrow.setVisibility(VISIBLE);
tv_state.setText("下拉刷新");
tv_time.setText("最后刷新" + getCurrentTime());
}

}

/**
* 获取当前系统时间,并格式化
*
* @return
*/
private String getCurrentTime() {
SimpleDateFormat format = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
return format.format(new Date());
}

/**
* 提供监听接口,监听加载数据
*/
private OnRefreshListener onRefreshListener;

public void setOnRefreshListener(OnRefreshListener onRefreshListener) {
this.onRefreshListener = onRefreshListener;
}

public interface OnRefreshListener {
void onPullRefresh();
void onLoadingMore();
}

/**
* scrollState:
* SCROLL_STATE_IDLE = 0;闲置状态,手指触摸结束
* SCROLL_STATE_TOUCH_SCROLL = 1;手指触摸滚动,就是手指按着滑动
* SCROLL_STATE_FLING = 2;惯性滑动,就是手指快速滑动
*
* @param view
* @param scrollState
*/
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
/**
* @return The number of items owned by the Adapter associated with this
*         AdapterView. (This is the number of data items, which may be
*         larger than the number of visible views.)
*/
if (scrollState == SCROLL_STATE_IDLE
&& getLastVisiblePosition() == (getCount() - 1)
&& !isLoadingMore) {
isLoadingMore=true;
footerView.setPadding(0, 0, 0, 0);
setSelection(getCount());
if (onRefreshListener!=null){
onRefreshListener.onLoadingMore();
}
}
}

@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
}


这样就可以在布局中使用自己的RefreshListview了:

<com.chenshi.myrefleshview.RefreshListView
android:id="@+id/refreshlistview"
android:layout_width="match_parent"
android:layout_height="match_parent" />


demo下载:demo下载链接

能看到大家的评论,我会很开心的!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: