/** * 根据当前ListView的滚动状态来设定 {@link #ableToPull} * 的值,每次都需要在onTouch中第一个执行,这样可以判断出当前应该是滚动ListView,还是应该进行下拉。 * * @param event */ private void setIsAbleToPull(View view, MotionEvent event) { boolean oldVal = this.ableToPull; this.ableToPull = this.pullableView.isPullable(view, event); if (this.ableToPull) { if (oldVal == false) { yDown = event.getRawY(); } } else if (headerLayoutParams.topMargin != hideHeaderHeight) { headerLayoutParams.topMargin = hideHeaderHeight; header.setLayoutParams(headerLayoutParams); } if (pullableView.getView() instanceof ListView) { View firstChild = ((ListView) pullableView.getView()).getChildAt(0); if (firstChild != null) { int firstVisiblePos = ((ListView) pullableView.getView()).getFirstVisiblePosition(); if (firstVisiblePos == 0 && firstChild.getTop() == 0) { if (!ableToPull) { yDown = event.getRawY(); } // 如果首个元素的上边缘,距离父布局值为0,就说明ListView滚动到了最顶部,此时应该允许下拉刷新 ableToPull = true; } else { if (headerLayoutParams.topMargin != hideHeaderHeight) { headerLayoutParams.topMargin = hideHeaderHeight; header.setLayoutParams(headerLayoutParams); } ableToPull = false; } } else { // 如果ListView中没有元素,也应该允许下拉刷新 ableToPull = true; } } }
/** 当ListView被触摸时调用,其中处理了各种下拉刷新的具体逻辑。 */ @Override public boolean onTouch(View v, MotionEvent event) { setIsAbleToPull(v, event); boolean retVal = false; if (ableToPull) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: yDown = event.getRawY(); // if(log.isDebugEnabled()){ // log.debug("Touch down, y position :"+yDown); // } break; case MotionEvent.ACTION_MOVE: float yMove = event.getRawY(); int distance = (int) (yMove - yDown); // if(log.isDebugEnabled()){ // log.debug("Touch down and move, y position :"+yMove+", move distance :"+distance); // } // 如果手指是下滑状态,并且下拉头是完全隐藏的,就屏蔽下拉事件 if (distance <= 0 && headerLayoutParams.topMargin <= hideHeaderHeight) { return false; } if (distance < touchSlop) { return false; } if (!pullStarted) { // if(log.isDebugEnabled()){ // log.debug("Pull started, touchSlop = "+touchSlop); // } pullableView.pullStarted(v); pullStarted = true; } retVal = true; if (currentStatus != STATUS_REFRESHING) { if (headerLayoutParams.topMargin > 0) { currentStatus = STATUS_RELEASE_TO_REFRESH; } else { currentStatus = STATUS_PULL_TO_REFRESH; } // 通过偏移下拉头的topMargin值,来实现下拉效果 headerLayoutParams.topMargin = (distance / 2) + hideHeaderHeight; header.setLayoutParams(headerLayoutParams); } break; case MotionEvent.ACTION_UP: default: if (pullStarted) { pullableView.pullEnded(v); pullStarted = false; retVal = true; } if (currentStatus == STATUS_RELEASE_TO_REFRESH) { // 松手时如果是释放立即刷新状态,就去调用正在刷新的任务 setOnRefreshing(true); } else if (currentStatus == STATUS_PULL_TO_REFRESH) { // 松手时如果是下拉状态,就去调用隐藏下拉头的任务 hideHeader(); } break; } // 时刻记得更新下拉头中的信息 if (currentStatus == STATUS_PULL_TO_REFRESH || currentStatus == STATUS_RELEASE_TO_REFRESH) { updateHeaderView(); // 当前正处于下拉或释放状态,要让ListView失去焦点,否则被点击的那一项会一直处于选中状态 pullableView.getView().setPressed(false); pullableView.getView().setFocusable(false); pullableView.getView().setFocusableInTouchMode(false); lastStatus = currentStatus; // 当前正处于下拉或释放状态,通过返回true屏蔽掉ListView的滚动事件 } } return retVal; }