码迷,mamicode.com
首页 > 移动开发 > 详细

Android listview的下拉刷新

时间:2015-04-07 21:47:12      阅读:215      评论:0      收藏:0      [点我收藏+]

标签:android   下拉刷新   listview   

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">好久没有写博客了,今天我就写一个listview的下拉刷新分享给大家,希望对大家学习或者工作上有所帮助,其实呢,大家都知道,在现在的app当中,下拉刷新是比较常用的功能,用到的地方太多了,所以,今天我也就结合自己的思想给家真理一下,那么好,接下来,让我们一起学习,让你分分钟写出自己想要的自定义listview下拉刷新</span>


一:实现思路

1.实现将listview添加头部view,也就是下拉要出现是头部布局

2.将头部的view给隐藏(这点需要特别注意)

3.给listview设置滑动监听(用于判断是否到头部)

4.设置手势事件,手指移动的时候的所做的操作


二:源码实例

1.自定义控件

package com.zengtao.refreshview;

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

import android.annotation.SuppressLint;
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;

import com.zengtao.pulltorefreshtest.R;

/**
 * 下拉刷新listview
 * 
 * @author zengtao 2015年3月17日 下午7:13:55
 */
public class RefreshableView extends ListView implements OnScrollListener {

	/** 下拉刷新的头部 */
	private View headerView;

	/** 头部的箭头 */
	private ImageView arrawImage;

	/** 更新刷新之后的时间 */
	private TextView lastUpdatTime;

	/** 刷新的一个状态 */
	private TextView stateMessage;

	/** 加载进度 */
	private ProgressBar progressBar;

	/** 获取头部文件的高度 */
	private int headerHeight;

	/** 当前第一个可见的位置 */
	private int firstVisibleItem;

	/** 标记当前是否能刷新 */
	private boolean isReflash;

	/** 按下的y值 */
	private int startY;

	/** 下拉的状态 */
	private int state;

	/** 正常状态 */
	private final int NONE = 0;

	/** 提示下拉刷新状态 */
	private final int PULL = 1;

	/** 提示释放刷新状态 */
	private final int REFPULL = 2;

	/** 提示正在刷新 */
	private final int LOADING = 3;

	/** ListView 当前滚动位置 */
	private int scorellStatep;

	/** 数据回调接口 */
	private IReflashLinster iReflashLinster;

	public RefreshableView(Context context) {
		super(context);
		initView(context);
	}

	public RefreshableView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		initView(context);
	}

	public RefreshableView(Context context, AttributeSet attrs) {
		super(context, attrs);
		initView(context);
	}

	/**
	 * 作用:初始化下拉刷新的头部
	 * 
	 * @param context
	 *            :上下文
	 */
	@SuppressLint("InflateParams")
	private void initView(Context context) {
		headerView = LayoutInflater.from(context).inflate(
				R.layout.pull_to_refresh, null);
		// 初始化试图
		arrawImage = (ImageView) headerView.findViewById(R.id.iv_arrow);
		stateMessage = (TextView) headerView.findViewById(R.id.pull_state);
		lastUpdatTime = (TextView) headerView.findViewById(R.id.lastupdatetime);
		progressBar = (ProgressBar) headerView.findViewById(R.id.progress_bar);

		// 通知父布局,才能取到多高,否则为0
		measureView(headerView);
		headerHeight = headerView.getMeasuredHeight();
		topPadding(-headerHeight);
		this.addHeaderView(headerView);
		this.setOnScrollListener(this);
	}

	/**
	 * 通知父布局我该占取多少的height 和 width
	 * 
	 * @param view
	 *            :试图布局
	 */
	private void measureView(View view) {
		ViewGroup.LayoutParams p = view.getLayoutParams();
		if (p == null) {
			p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
					ViewGroup.LayoutParams.WRAP_CONTENT);
		}
		int width = ViewGroup.getChildMeasureSpec(0, 0, p.width);
		int tempHeight = p.height;
		int height;
		if (tempHeight > 0) {
			height = MeasureSpec.makeMeasureSpec(tempHeight,
					MeasureSpec.EXACTLY);
		} else {
			height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
		}
		view.measure(width, height);
	}

	/**
	 * 设置header布局的上边距
	 * 
	 * @param topHeight
	 *            : 上边距高度
	 */
	private void topPadding(int topPadding) {
		headerView.setPadding(headerView.getPaddingLeft(), topPadding,
				headerView.getPaddingRight(), headerView.getPaddingBottom());
		headerView.invalidate();
	}

	@Override
	public void onScrollStateChanged(AbsListView view, int scrollState) {
		this.scorellStatep = scrollState;
	}

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

	@SuppressLint("ClickableViewAccessibility")
	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		switch (ev.getAction()) {
		case MotionEvent.ACTION_DOWN:
			// listview 已经滑到头部
			if (firstVisibleItem == 0) {
				isReflash = true;
				startY = (int) ev.getY();
			}
			break;
		case MotionEvent.ACTION_MOVE:
			// 移动的时候所做的操作
			onMove(ev);
			break;
		case MotionEvent.ACTION_UP:
			// 松开的时候看是处于什么状态
			if (state == REFPULL) {
				state = LOADING; // 可以加载数据了
				reflashViewBySate();
				reflashComplete();
				iReflashLinster.reflash();
			} else if (state == PULL) {
				state = NONE;
				isReflash = false;
				reflashViewBySate();
			}
			break;
		}
		return super.onTouchEvent(ev);
	}

	/**
	 * 手指移动的时候的所做的操作
	 * 
	 * @param ev
	 */
	private void onMove(MotionEvent ev) {
		// 是不是能刷新
		if (!isReflash) {
			return;
		}
		// 当前移动的位置
		int tempY = (int) ev.getY();
		int spance = tempY - startY;
		// 顶部布局是一点一点的显示出来,所以要不停的设置顶部布局
		int topPadding = spance - headerHeight;
		
		switch (state) {
		case NONE:
			// 当用户更下拉的时候状态:提示下拉状态
			if (spance > 0) {
				state = PULL;
			}
			break;
		case PULL:
			topPadding(topPadding);
			// 用户下拉超过一定并且处于滑动滚动的的时候:提示松开刷新状态
			if (spance > headerHeight + 20
					&& scorellStatep == SCROLL_STATE_TOUCH_SCROLL) {
				state = REFPULL;
				reflashViewBySate();
			}
			break;
		case REFPULL:
			topPadding(topPadding);
			// 当用户回滚到低于一定高度的时候:提示下拉刷新状态
			if (spance < headerHeight + 20) {
				state = PULL;
				reflashViewBySate();
			} else if (spance <= 0) {
				state = NONE;
				isReflash = false;
				reflashViewBySate();
			}
		}
	}

	/**
	 * 根据状态:在去决定是否刷新数据和加载布局
	 */
	private void reflashViewBySate() {

		// 动画效果
		RotateAnimation animation = new RotateAnimation(0, 180,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f);
		animation.setDuration(500);
		animation.setFillAfter(true);

		// 动画效果
		RotateAnimation animation1 = 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);
			arrawImage.clearAnimation();
			
			break;
		case PULL:
			arrawImage.setVisibility(View.VISIBLE);
			progressBar.setVisibility(View.GONE);

			stateMessage.setText("下拉可以刷新");
			arrawImage.clearAnimation();
			arrawImage.setAnimation(animation1);
			break;
		case REFPULL:
			arrawImage.setVisibility(View.VISIBLE);
			progressBar.setVisibility(View.GONE);

			stateMessage.setText("松开可以刷新");
			arrawImage.clearAnimation();
			arrawImage.setAnimation(animation);
			break;
		case LOADING:
			topPadding(50);
			progressBar.setVisibility(View.VISIBLE);
			arrawImage.setVisibility(View.GONE);

			stateMessage.setText("正在刷新...");
			arrawImage.clearAnimation();
			break;
		}
	}

	/**
	 * 刷新完成之后,更改刷新时间
	 */
	@SuppressLint("SimpleDateFormat")
	public void reflashComplete() {
		state = NONE;
		isReflash = false;
		reflashViewBySate();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss");
		Date date = new Date(System.currentTimeMillis());
		String time = sdf.format(date);
		lastUpdatTime.setText(time);
	}

	public interface IReflashLinster {	
		public void reflash();
	}

	public void setIReflashLinster(IReflashLinster iReflashLinster) {
		this.iReflashLinster = iReflashLinster;
	}

2.Maintivity 在主界面中的使用

package com.zengtao.pulltorefreshtest;

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

import com.zengtao.refreshview.RefreshableView;
import com.zengtao.refreshview.RefreshableView.IReflashLinster;

public class MainActivity extends Activity implements IReflashLinster {
	private RefreshableView listView;
	private ArrayAdapter<String> Adapter;
	private String[] str = { "傻逼才是王道 1", "傻逼才是王道  2", "text 3", "傻逼才是王道 4", "傻逼才是王道 5",
			"傻逼才是王道 6", "傻逼才是王道 7", "傻逼才是王道 8", "傻逼才是王道 9", "傻逼才是王道 10", "傻逼才是王道 11",
			"傻逼才是王道 12", "傻逼才是王道 13", "傻逼才是王道 14", "傻逼才是王道 1", "傻逼才是王道 2", "傻逼才是王道 3",
			"傻逼才是王道 4", "傻逼才是王道 5", "傻逼才是王道 6", "傻逼才是王道 7", "傻逼才是王道 8", "傻逼才是王道 9",
			"傻逼才是王道 10", "傻逼才是王道 11", "傻逼才是王道 12", "傻逼才是王道 13", "傻逼才是王道 14" };

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_main);
		initView();
	}

	private void initView() {
		listView = (RefreshableView) findViewById(R.id.listview);
		listView.setIReflashLinster(this);
		Adapter = new ArrayAdapter<String>(this,
				android.R.layout.simple_list_item_1, str);
		listView.setAdapter(Adapter);
	}

	@Override
	public void reflash() {
		Handler handler = new Handler();
		handler.postDelayed(new Runnable() {

			@Override
			public void run() {
				
			}
		}, 3000);
	}
}

以上变可完成一个自定义的listview的自定义和使用,希望对大家有所帮助,我写的不好,大家请勿怪。


Android listview的下拉刷新

标签:android   下拉刷新   listview   

原文地址:http://blog.csdn.net/u011546655/article/details/44924773

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!