您的位置:首页 > 其它

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

2017-05-31 00:02 441 查看
第一步:

自定义一个类继承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>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐