ListView下拉刷新(PullToRefresh)

1、首先准备一个ListView;(代码不粘)

2、设置下拉是出现的头部布局header.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="match_parent"
    android:orientation="vertical" >

    <!-- 下拉时,显示的背面布局 -->
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingBottom="10dip"
        android:paddingTop="10dip" >

        <LinearLayout
            android:id="@+id/layout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:gravity="center"
            android:orientation="vertical" >

            <!-- 下拉刷新文字提示部分 -->
            <TextView
                android:id="@+id/tip"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="下拉可以刷新!" />

            <TextView
                android:id="@+id/lastUpdate_time"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />
        </LinearLayout>

        <!-- 箭头 -->
        <ImageView
            android:id="@+id/arrow"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="20dip"
            android:layout_toLeftOf="@id/layout"
            android:src="@drawable/pull_to_refresh_arrow" />

        <!-- 进度条默认不显示,只有加载更多的时候才显示 -->
        <ProgressBar
            android:id="@+id/progress"
            style="?android:attr/progressBarStyleSmall"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="20dip"
            android:layout_toLeftOf="@id/layout"
            android:visibility="gone" />
    </RelativeLayout>

</LinearLayout>

3、新建类RefreshListView类:

package com.example.pulltorefresh;

import java.text.SimpleDateFormat;
import java.util.Date;

import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;

public class RefreshListView extends ListView implements OnScrollListener {

	public RefreshListView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		initView(context);
		// TODO Auto-generated constructor stub
	}

	public RefreshListView(Context context, AttributeSet attrs) {
		super(context, attrs);
		initView(context);
		// TODO Auto-generated constructor stub
	}

	public RefreshListView(Context context) {
		super(context);
		initView(context);
		// TODO Auto-generated constructor stub
	}

	View header; // 顶部布局文件
	int headerHeight; // 顶部布局文件的高度

	// 初始化界面,添加顶部布局文件到ListView
	private void initView(Context context) {
		LayoutInflater inflater = LayoutInflater.from(context);
		header = inflater.inflate(R.layout.header, null);

		measureView(header);// 通知父布局,占用的宽和高

		headerHeight = header.getMeasuredHeight();
		// Log.i("headerHeight", "headerHeight"+headerHeight);
		topPadding(-headerHeight); // 传入的是高度值的负值,隐藏顶部布局
		this.addHeaderView(header); // “添加”顶部布局文件

		this.setOnScrollListener(this); // 设置滚动的监听事件
	}

	// 设置header布局上边距
	private void topPadding(int topPadding) {
		header.setPadding(header.getPaddingLeft(), topPadding,
				header.getPaddingRight(), header.getPaddingBottom());
		header.invalidate();
	}

	// 通知父布局,占用的宽和高
	private void measureView(View view) {
		ViewGroup.LayoutParams lp = view.getLayoutParams();
		if (lp == null) {
			lp = new ViewGroup.LayoutParams(
					ViewGroup.LayoutParams.WRAP_CONTENT,
					ViewGroup.LayoutParams.WRAP_CONTENT);
		}

		int width = ViewGroup.getChildMeasureSpec(0, 0, lp.width);
		int height;
		int tempHeight = lp.height;
		if (tempHeight > 0) {
			height = MeasureSpec.makeMeasureSpec(tempHeight,
					MeasureSpec.EXACTLY);
		} else {
			height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
		}

		view.measure(width, height);
	}

	int curScrollState;// 当前滚动状态

	@Override
	public void onScrollStateChanged(AbsListView view, int scrollState) {
		// TODO Auto-generated method stub
		this.curScrollState = scrollState;
	}

	int firstVisibleItem;// 当前界面第一个可见的item的位置;
	boolean isRemark;// 标记当前是在ListView最顶端摁下的;
	int startY;// 开始Y值

	@Override
	public void onScroll(AbsListView view, int firstVisibleItem,
			int visibleItemCount, int totalItemCount) {
		// TODO Auto-generated method stub
		this.firstVisibleItem = firstVisibleItem;// 通过判断firstVisibleItem,来判断是否在最顶端
	}

	IReflashListenter reflashListenter;
	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		// TODO Auto-generated method stub
		switch (ev.getAction()) {
		case MotionEvent.ACTION_DOWN:
			if (firstVisibleItem == 0) {
				isRemark = true;
				startY = (int) ev.getY();
			}
			break;

		case MotionEvent.ACTION_MOVE:
			onMove(ev);
			break;
		case MotionEvent.ACTION_UP:
			if (state == RELESH) {
				state = REFRESHING;
				
				// 加载最新数据
				reflashViewByState();
				
				reflashListenter.onReflash();
				
			} else if (state == PULL) {
				state=NONE;
				isRemark=false;
				reflashViewByState();
			}
			break;

		}

		return super.onTouchEvent(ev);
	}

	// 判断移动过程中的操作
	int state; // 当前状态
	final int NONE = 0; // 正常状态
	final int PULL = 1; // 提示下拉状态
	final int RELESH = 2; // 提示松开释放状态
	final int REFRESHING = 3; // 正在刷新状态

	private void onMove(MotionEvent ev) {
		// TODO Auto-generated method stub
		if (!isRemark) {
			return;
		}
		int tempY = (int) ev.getY();
		int space = tempY - startY; // 记录拖动距离
		int topPadding = space - headerHeight;
		switch (state) {
		case NONE:
			if (space > 0) {
				state = PULL;
			}
			reflashViewByState();
			break;

		case PULL:
			topPadding(topPadding);
			if (space > headerHeight + 30
					&& curScrollState == SCROLL_STATE_TOUCH_SCROLL) {
				state = RELESH;
				reflashViewByState();
			}
			break;

		case RELESH:
			topPadding(topPadding);
			if (space < headerHeight + 30) {
				state = PULL;
				reflashViewByState();
			} else if (space <= 0) {
				state = NONE;
				isRemark = false;
				reflashViewByState();
			}
			break;

		}
	}

	// 根据当前状态改变界面显示
	private void reflashViewByState() {
		TextView tip = (TextView) header.findViewById(R.id.tip);
		ImageView arrow = (ImageView) header.findViewById(R.id.arrow);
		ProgressBar progress = (ProgressBar) header.findViewById(R.id.progress);

		RotateAnimation animation1 = new RotateAnimation(0, 180,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f);
		animation1.setDuration(500);
		animation1.setFillAfter(true);
		RotateAnimation animation2 = new RotateAnimation(180, 0,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f);
		animation1.setDuration(500);
		animation1.setFillAfter(true);
		
		switch (state) {
		case NONE:
			topPadding(-headerHeight);
			arrow.clearAnimation();
			break;

		case PULL:
			arrow.setVisibility(View.VISIBLE);
			progress.setVisibility(View.GONE);
			tip.setText("下拉可以刷新!");
			arrow.clearAnimation();
			arrow.setAnimation(animation2);
			break;
		case RELESH:
			arrow.setVisibility(View.VISIBLE);
			progress.setVisibility(View.GONE);
			tip.setText("松开可以刷新!");
			arrow.clearAnimation();
			arrow.setAnimation(animation1);
			break;
		case REFRESHING:
			topPadding(50);
			arrow.setVisibility(View.GONE);
			progress.setVisibility(View.VISIBLE);
			arrow.clearAnimation();
			tip.setText("正在刷新...");
			break;
		}
	}
	
	//获取完数据
	public void reflashComplete(){
		state = NONE;
		isRemark = false;
		reflashViewByState();
		TextView lastupdatetime = (TextView) header
				.findViewById(R.id.lastUpdate_time);
		SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss");
		Date date = new Date(System.currentTimeMillis());
		String time = format.format(date);
		lastupdatetime.setText(time);
	}
	
	public void setInterface(IReflashListenter reflashListenter){
		this.reflashListenter=reflashListenter;
	}
	
	//刷新数据接口
	public interface IReflashListenter{
		public void onReflash();
	}
}

4、MainActivity:

package com.example.pulltorefresh;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.SimpleAdapter;

import com.example.pulltorefresh.RefreshListView.IReflashListenter;

public class MainActivity extends Activity implements IReflashListenter, OnItemClickListener {
	private RefreshListView listView;
	private int NewsIcon[] = { R.drawable.tools1, R.drawable.tools2,
			R.drawable.tools3, R.drawable.tools4, R.drawable.games1,
			R.drawable.games2, R.drawable.games3, R.drawable.games4,
			R.drawable.games5, R.drawable.games6 };
	private String NewsName[] = { "ToolsItem1", "ToolsItem2", "ToolsItem3",
			"ToolsItem4", "GamesItem1", "GamesItem2", "GamesItem3",
			"GamesItem4", "GamesItem5", "GamesItem6" };
	private SimpleAdapter adapter;
	private List<Map<String, Object>> NewsDataList;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		listView = (RefreshListView) findViewById(R.id.newsListView);
		listView.setInterface(this);
		NewsDataList = new ArrayList<Map<String, Object>>();
		adapter = new SimpleAdapter(this, getNewsData(),
				R.layout.news_tab_item,
				new String[] { "NewsImage", "NewsName" }, new int[] {
						R.id.newsImageViewItem, R.id.newssName });
		listView.setAdapter(adapter);
		listView.setOnItemClickListener(this);
	}
	
	

	private List<? extends Map<String, ?>> getNewsData() {
		// TODO Auto-generated method stub
		for (int i = 0; i < NewsIcon.length; i++) {
			Map<String, Object> GamesMap = new HashMap<String, Object>();
			GamesMap.put("NewsImage", NewsIcon[i]);
			GamesMap.put("NewsName", NewsName[i]);
			NewsDataList.add(GamesMap);
		}
		return NewsDataList;
	}

	//获取刷新数据
	private List<? extends Map<String, ?>> getReflashNewsData() {
		// TODO Auto-generated method stub
		for (int i = 0; i < 2; i++) {
			Map<String, Object> GamesMap = new HashMap<String, Object>();
			GamesMap.put("NewsImage", NewsIcon[i]);
			GamesMap.put("NewsName", NewsName[i]+"刷新数据"+i);
			NewsDataList.add(0,GamesMap);
		}
		return NewsDataList;
	}
	
	@Override
	public void onItemClick(AdapterView<?> parent, View view, int position,
			long id) {
		// ListView的点击事件
		
	}

	@Override
	public void onReflash() {
		// TODO Auto-generated method stub
		Handler handler=new Handler();
		handler.postDelayed(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				//获取最新数据
				getReflashNewsData();
				//通知界面显示刷新数据				
				adapter = new SimpleAdapter(MainActivity.this, NewsDataList,
						R.layout.news_tab_item,
						new String[] { "NewsImage", "NewsName" }, new int[] {
								R.id.newsImageViewItem, R.id.newssName });   //传入的是整个(新旧)NewsDataList
				listView.setAdapter(adapter);
				//通知ListView刷新数据完毕
				listView.reflashComplete();
			}
		}, 2000);//此处是为了“表面上看上去有刷新延迟的效果”,实际应用中不需要
		
	}

}

5、效果图:


ListView下拉刷新(PullToRefresh)_第1张图片
ListView下拉刷新(PullToRefresh)_第2张图片


ListView下拉刷新(PullToRefresh)_第3张图片


ListView下拉刷新(PullToRefresh)_第4张图片


ListView下拉刷新(PullToRefresh)_第5张图片

完整代码:https://github.com/songshimvp/AndroidStudy/tree/master/PullToRefresh

你可能感兴趣的:(android,ListView,下拉刷新)