<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">今天项目也快结束了,就写篇博客吧,记录一下我对ListView的下拉刷新与底部载入更多的一点理解[/b]</span>
首先我们知道ListView是没有下拉刷新的接口的,我们要借助现有的功能去扩展更多的功能我们就需要对ListView做一点修改,使它满足我们的需求:
一、ListView的表面理解就是List的格式显示的View,也就是要一行一行的显示,对ListView添加适配器这是必不可少的。所以我们修改以后的ListView当然也可以添加适配器等等常见的对ListView的操作;
二、要捕捉我们对列表界面的操作,下拉或者滚动到底部必须要有对事件的监听器,这里就尤为重要了,我们知道对按钮添加监听器,我们可以捕获到我们对某个按钮施加了操作,然后就执行我们的操作,这里的下拉或者滚动到底部,我们当然也需要捕捉到这个动作,然后执行我们想要执行的动作;
三、原理我们知道啦,现在就剩下怎么去捕获这个动作,然后捕获动作后我们怎么添加入我们想要的操作。只要捕获到动作,你想干什么我不关心,因为需求各式各样;
四、在捕获到动作以后我们开始给用户点反应。。。。。
[b]下边我们来看看这个Demo的代码
一、继承ListView
package com.example.pulldownview;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ListView;
/**
* <p>一个可以监听ListView是否滚动到最顶部或最底部的自定义控件</p>
* 只能监听由触摸产生的,如果是ListView本身Flying导致的,则不能监听</br>
* 如果加以改进,可以实现监听scroll滚动的具体位置等
* @author solo ho</br> Email:kjsoloho@gmail.com
*/
public class ScrollOverListView extends ListView {
private static final String TAG = "ScrollOverListView";
private static final boolean DEBUG = false;
private int mLastY;
private int mTopPosition;
private int mBottomPosition;
public ScrollOverListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public ScrollOverListView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ScrollOverListView(Context context) {
super(context);
init();
}
private void init(){
mTopPosition = 0;
mBottomPosition = 0;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
if (DEBUG) Log.d(TAG, "onInterceptTouchEvent Action down");
mLastY = (int) ev.getRawY();
}
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
final int y = (int) ev.getRawY();
boolean isHandled = false;
switch(action){
case MotionEvent.ACTION_DOWN:{
if (DEBUG) Log.d(TAG, "action down");
mLastY = y;
isHandled = mOnScrollOverListener.onMotionDown(ev);
if (isHandled) {
break;
}
break;
}
case MotionEvent.ACTION_MOVE:{
if (DEBUG) Log.d(TAG, "action move");
final int childCount = getChildCount();
if(childCount == 0) {
break;
}
final int itemCount = getAdapter().getCount() - mBottomPosition;
final int deltaY = y - mLastY;
if (DEBUG) Log.d(TAG, "lastY=" + mLastY +" y=" + y);
final int firstTop = getChildAt(0).getTop();
final int listPadding = getListPaddingTop();
final int lastBottom = getChildAt(childCount - 1).getBottom();
final int end = getHeight() - getPaddingBottom();
final int firstVisiblePosition = getFirstVisiblePosition();
isHandled = mOnScrollOverListener.onMotionMove(ev, deltaY);
if(isHandled){
break;
}
//DLog.d("firstVisiblePosition=%d firstTop=%d listPaddingTop=%d deltaY=%d", firstVisiblePosition, firstTop, listPadding, deltaY);
if (firstVisiblePosition <= mTopPosition && firstTop >= listPadding && deltaY > 0) {
if (DEBUG) Log.d(TAG, "action move pull down");
isHandled = mOnScrollOverListener.onListViewTopAndPullDown(ev, deltaY);
if(isHandled){
break;
}
}
// DLog.d("lastBottom=%d end=%d deltaY=%d", lastBottom, end, deltaY);
if (firstVisiblePosition + childCount >= itemCount && lastBottom <= end && deltaY < 0) {
if (DEBUG) Log.d(TAG, "action move pull up");
isHandled = mOnScrollOverListener.onListViewBottomAndPullUp(ev, deltaY);
if(isHandled){
break;
}
}
break;
}
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:{
if (DEBUG) Log.d(TAG, "action move pull up");
isHandled = mOnScrollOverListener.onMotionUp(ev);
if (isHandled) {
break;
}
break;
}
}
mLastY = y;
if (isHandled) {
return true;
}
return super.onTouchEvent(ev);
}
/**空的*/
private OnScrollOverListener mOnScrollOverListener = new OnScrollOverListener(){
@Override
public boolean onListViewTopAndPullDown(MotionEvent event, int delta) {
return false;
}
@Override
public boolean onListViewBottomAndPullUp(MotionEvent event, int delta) {
return false;
}
@Override
public boolean onMotionDown(MotionEvent ev) {
return false;
}
@Override
public boolean onMotionMove(MotionEvent ev, int delta) {
return false;
}
@Override
public boolean onMotionUp(MotionEvent ev) {
return false;
}
};
// =============================== public method ===============================
/**
* 可以自定义其中一个条目为头部,头部触发的事件将以这个为准,默认为第一个
*
* @param index 正数第几个,必须在条目数范围之内
*/
public void setTopPosition(int index){
if(index < 0)
throw new IllegalArgumentException("Top position must > 0");
mTopPosition = index;
}
/**
* 可以自定义其中一个条目为尾部,尾部触发的事件将以这个为准,默认为最后一个
*
* @param index 倒数第几个,必须在条目数范围之内
*/
public void setBottomPosition(int index){
if(index < 0)
throw new IllegalArgumentException("Bottom position must > 0");
mBottomPosition = index;
}
/**
* 设置这个Listener可以监听是否到达顶端,或者是否到达低端等事件</br>
*
* @see OnScrollOverListener
*/
public void setOnScrollOverListener(OnScrollOverListener onScrollOverListener){
mOnScrollOverListener = onScrollOverListener;
}
/**
* 滚动监听接口</br>
* @see ScrollOverListView#setOnScrollOverListener(OnScrollOverListener)
*
* @author solo ho</br> Email:kjsoloho@gmail.com
*/
public interface OnScrollOverListener {
/**
* 到达最顶部触发
*
* @param delta 手指点击移动产生的偏移量
* @return
*/
boolean onListViewTopAndPullDown(MotionEvent event, in