ListView下拉刷新和上拉加载更多的实现

第一步:

自定义一个类继承ListView

package com.itheima.pulltorefreshlistview.view;


import com.itheima.pulltorefreshlistview.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.ProgressBar;
import android.widget.TextView;


public class PullToRefreshListView extends ListView {


private View headerView;
private float downY;
private int headerViewHeight;
/** 状态:下拉刷新 */
private static final int STATE_PULL_TO_REFRESH = 0;
/** 状态:松开刷新 */
private static final int STATE_RELEASE_REFRESH = 1;
/** 状态:正在刷新 */
private static final int STATE_REFRESHING = 2;
/** 当前状态 */
private int currentState = STATE_PULL_TO_REFRESH; // 默认是下拉刷新状态
private ImageView iv_arrow;
private ProgressBar progress_bar;
private TextView tv_state;
private RotateAnimation upAnim;
private RotateAnimation downAnim;
private OnRefreshingListener mOnRefreshingListener;
private View footerView;
private int footerViewHeight;
/** 正在加载更多 */
private boolean loadingMore;


public PullToRefreshListView(Context context, AttributeSet attrs) {
super(context, attrs);
initHeaderView();
initFooterView();
}

private void initHeaderView() {
headerView = View.inflate(getContext(), R.layout.header_view, null);
iv_arrow = (ImageView) headerView.findViewById(R.id.iv_arrow);
progress_bar = (ProgressBar) headerView.findViewById(R.id.progress_bar);
showRefreshingProgressBar(false);
tv_state = (TextView) headerView.findViewById(R.id.tv_state);
headerView.measure(0, 0); // 主动触发测量,mesure内部会调用onMeasure
headerViewHeight = headerView.getMeasuredHeight();
hideHeaderView();
super.addHeaderView(headerView);
upAnim = createRotateAnim(0f, -180f);
downAnim = createRotateAnim(-180f, -360f);
}

private void initFooterView() {
footerView = View.inflate(getContext(), R.layout.footer_view, null);
footerView.measure(0, 0);// 主动触发测量,mesure内部会调用onMeasure
footerViewHeight = footerView.getMeasuredHeight();
hideFooterView();
super.addFooterView(footerView);

super.setOnScrollListener(new OnScrollListener() {

// 当ListView滚动的状态发生改变的时候会调用这个方法
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == OnScrollListener.SCROLL_STATE_IDLE // ListView处于空闲状态
&& getLastVisiblePosition() == getCount() - 1 // 界面上可见的最后一条item是ListView中最后的一条item
&& loadingMore == false // 如果当前没有去做正在加载更多的事情
) {
loadingMore = true;
showFooterView();
setSelection(getCount() - 1);

if (mOnRefreshingListener != null) {
mOnRefreshingListener.onLoadMore();
}
}
}

// 当ListView滚动的时候会调用这个方法
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

}
});
}


private void hideFooterView() {
int paddingTop = -footerViewHeight;
setFooterViewPaddingTop(paddingTop);
}

private void showFooterView() {
int paddingTop = 0;
setFooterViewPaddingTop(paddingTop);
}


private void setFooterViewPaddingTop(int paddingTop) {
footerView.setPadding(0, paddingTop, 0, 0);
}


/**
* 设置显示进度的圈圈
* @param showProgressBar 如果是true,则显示ProgressBar,否则的话显示箭头
*/
private void showRefreshingProgressBar(boolean showProgressBar) {
progress_bar.setVisibility(showProgressBar ? View.VISIBLE : View.GONE);
iv_arrow.setVisibility(!showProgressBar ? View.VISIBLE : View.GONE);

if (showProgressBar) {
iv_arrow.clearAnimation(); // 有动画的View要清除动画才能真正的隐藏
}
}


/**
* 创建旋转动画
* @param fromDegrees 从哪个角度开始转
* @param toDegrees 转到哪个角度
* @return 
*/
private RotateAnimation createRotateAnim(float fromDegrees, float toDegrees) {
int pivotXType = RotateAnimation.RELATIVE_TO_SELF; // 旋转点的参照物
int pivotYType = RotateAnimation.RELATIVE_TO_SELF; // 旋转点的参照物
float pivotXValue = 0.5f; // 旋转点x方向的位置
float pivotYValue = 0.5f; // 旋转点y方向的位置
RotateAnimation ra = new RotateAnimation(fromDegrees, toDegrees, pivotXType, pivotXValue, pivotYType, pivotYValue);
ra.setDuration(300);
ra.setFillAfter(true); // 让动画停留在结束位置
return ra;
}


/** 隐藏HeaderView */
private void hideHeaderView() {
int paddingTop = -headerViewHeight;
setHeaderViewPaddingTop(paddingTop);
}

/** 显示HeaderView */
private void showHeaderView() {
int paddingTop = 0;
setHeaderViewPaddingTop(paddingTop);
}


/**
* 设置HeaderView的paddingTop
* @param paddingTop
*/
private void setHeaderViewPaddingTop(int paddingTop) {
headerView.setPadding(0, paddingTop, 0, 0);
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
downY = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
if (currentState == STATE_REFRESHING) {
// 如果当前已经是“正在刷新“的状态了,则不用去处理下拉刷新了
return super.onTouchEvent(ev);
}

int fingerMoveDistanceY = (int) (ev.getY() - downY); // 手指移动的距离
// 如果是向下滑动,并且界面上可见的第一条item是ListView的索引为0的item时我们才处理下拉刷新的操作
if (fingerMoveDistanceY > 0 && getFirstVisiblePosition() == 0) {
int paddingTop = -headerViewHeight + fingerMoveDistanceY;
setHeaderViewPaddingTop(paddingTop);

if (paddingTop < 0 && currentState != STATE_PULL_TO_REFRESH) {
// 如果paddingTop小于0,说明HeaderView没有完全显示出来,则进入下拉刷新的状态
currentState = STATE_PULL_TO_REFRESH;
tv_state.setText("下拉刷新");
iv_arrow.startAnimation(downAnim);
showRefreshingProgressBar(false);
// 让箭头转一下
} else if (paddingTop >= 0 && currentState != STATE_RELEASE_REFRESH) {
// 如果paddingTop>=0,说明HeaderView已经完全显示出来,则进入松开刷新的状态
currentState = STATE_RELEASE_REFRESH;
tv_state.setText("松开刷新");
iv_arrow.startAnimation(upAnim);
showRefreshingProgressBar(false);

}
return true;
}
break;
case MotionEvent.ACTION_UP:
if (currentState == STATE_RELEASE_REFRESH) {
// 如果当前状态是松开刷新,并且抬起了手,则进入正在刷新状态
currentState = STATE_REFRESHING;
tv_state.setText("正在刷新");
showRefreshingProgressBar(true);
showHeaderView();

if (mOnRefreshingListener != null) {
mOnRefreshingListener.onRefreshing();
}
} else if (currentState == STATE_PULL_TO_REFRESH) {
// 如果抬起手时是下拉刷新状态,则把HeaderView完成隐藏
hideHeaderView();
}
break;
}
return super.onTouchEvent(ev);
}


public void setOnRefreshingListener(OnRefreshingListener mOnRefreshingListener) {
this.mOnRefreshingListener = mOnRefreshingListener;
}

/** ListView刷新的监听器 */
public interface OnRefreshingListener {
/** 当ListView可以刷新数据的时候会调用这个方法 */
void onRefreshing();
/** 当ListView可以加载更多 的时候会调用这个方法 */
void onLoadMore();
}


/** 联网刷新数据的操作已经完成了 */
public void onRefreshComplete() {
hideHeaderView();
currentState = STATE_PULL_TO_REFRESH;
showRefreshingProgressBar(false);
}


/** 加载更多新数据的操作已经完成了 */
public void onLoadmoreComplete() {
hideFooterView();
loadingMore = false;
}


}

添加头heade的布局

<?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"
    android:gravity="center_vertical" >
    
    <RelativeLayout 
        android:layout_width="50dp"
        android:layout_height="50dp">
        
        <ImageView 
            android:id="@+id/iv_arrow"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/arrow"
            android:layout_centerInParent="true"/>
        
        <ProgressBar 
            android:id="@+id/progress_bar"
            style="@android:style/Widget.ProgressBar"
            android:indeterminateDrawable="@drawable/progress_medium_white"
            android:layout_width="28dp"
            android:layout_height="28dp"
            android:layout_centerInParent="true"
            android:visibility="gone"/>
        
    </RelativeLayout>
    
    <LinearLayout 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="vertical">
        
        <TextView 
            android:id="@+id/tv_state"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#FF0000"
            android:text="下拉刷新"/>
        
        <TextView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#666666"
            android:textSize="12sp"
            android:text="最后刷新时间:2015-07-25 19:59:39"
            android:layout_marginTop="4dp"/>
        
    </LinearLayout>


</LinearLayout>

添加尾foot的布局:

<?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"
    android:gravity="center"  >
    
    <ProgressBar
        style="@android:style/Widget.ProgressBar"
        android:layout_width="28dp"
        android:layout_height="28dp"
        android:layout_marginTop="8dp"
        android:layout_marginBottom="8dp"
        android:indeterminateDrawable="@drawable/progress_medium_white"
        />
    
    <TextView 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="6dp"
        android:textColor="#FF0000"
        android:text="加载更多..."/>


</LinearLayout>

第二步:

MainActivity的类:

package com.itheima.pulltorefreshlistview;


import java.util.ArrayList;


import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.widget.ArrayAdapter;


import com.itheima.pulltorefreshlistview.view.PullToRefreshListView;
import com.itheima.pulltorefreshlistview.view.PullToRefreshListView.OnRefreshingListener;


public class MainActivity extends Activity {


    private PullToRefreshListView listView;
private ArrayList<String> datas;
private ArrayAdapter<String> adapter;


@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        listView = (PullToRefreshListView) findViewById(R.id.list_view);
        
        // 模拟数据
        datas = new ArrayList<String>();
        for (int i = 0; i < 20; i++) {
        datas.add("我又捡到钱了,好开心啊^_^ \t" + i);
}
        
        adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, datas);
        listView.setAdapter(adapter);
        
        listView.setOnRefreshingListener(new OnRefreshingListener() {

@Override
public void onRefreshing() {
reloadData();
}


@Override
public void onLoadMore() {
loadMore();
}
});
    }


/** 重新联网获取数据 */
protected void reloadData() {
new Handler().postDelayed(new Runnable() {

@Override
public void run() {
datas.add(0, "我是刷新出来的数据");
adapter.notifyDataSetChanged();
listView.onRefreshComplete();
}
}, 3000); // 模拟联网的耗时操作。  3秒钟后会调用run方法中的代码
}

/** 联网加载更多数据 */
protected void loadMore() {
new Handler().postDelayed(new Runnable() {

@Override
public void run() {
datas.add("我是加载更多出来的数据");
adapter.notifyDataSetChanged();
listView.onLoadmoreComplete();
}
}, 3000); // 模拟联网的耗时操作。  3秒钟后会调用run方法中的代码
}


}

MainActivity的布局:

<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=".MainActivity">


    <com.itheima.pulltorefreshlistview.view.PullToRefreshListView
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />


</RelativeLayout>












































  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值