private void animateOffsetToCorrectPosition() { mFrom = mCurrentOffsetTop; mFromDragPercent = mCurrentDragPercent; mAnimateToCorrectPosition.reset(); mAnimateToCorrectPosition.setDuration(MAX_OFFSET_ANIMATION_DURATION); mAnimateToCorrectPosition.setInterpolator(mDecelerateInterpolator); mRefreshView.clearAnimation(); mRefreshView.startAnimation(mAnimateToCorrectPosition); if (mRefreshing) { mBaseRefreshView.start(); if (mNotify) { if (mListener != null) { mListener.onRefresh(); } } } else { mBaseRefreshView.stop(); animateOffsetToStartPosition(); } mCurrentOffsetTop = mTarget.getTop(); mTarget.setPadding( mTargetPaddingLeft, mTargetPaddingTop, mTargetPaddingRight, mTotalDragDistance); }
private void setTargetOffsetTop(int offset, boolean requiresUpdate) { mTarget.offsetTopAndBottom(offset); mBaseRefreshView.offsetTopAndBottom(offset); mCurrentOffsetTop = mTarget.getTop(); if (requiresUpdate && android.os.Build.VERSION.SDK_INT < 11) { invalidate(); } }
@Override public void applyTransformation(float interpolatedTime, Transformation t) { int targetTop; int endTarget = mTotalDragDistance; targetTop = (mFrom + (int) ((endTarget - mFrom) * interpolatedTime)); int offset = targetTop - mTarget.getTop(); mCurrentDragPercent = mFromDragPercent - (mFromDragPercent - 1.0f) * interpolatedTime; mBaseRefreshView.setPercent(mCurrentDragPercent, false); setTargetOffsetTop(offset, false /* requires update */); }
private void setRefreshing(boolean refreshing, final boolean notify) { if (mRefreshing != refreshing) { mNotify = notify; ensureTarget(); mRefreshing = refreshing; if (mRefreshing) { mBaseRefreshView.setPercent(1f, true); animateOffsetToCorrectPosition(); } else { animateOffsetToStartPosition(); } } }
private void moveToStart(float interpolatedTime) { int targetTop = mFrom - (int) (mFrom * interpolatedTime); float targetPercent = mFromDragPercent * (1.0f - interpolatedTime); int offset = targetTop - mTarget.getTop(); mCurrentDragPercent = targetPercent; mBaseRefreshView.setPercent(mCurrentDragPercent, true); mTarget.setPadding( mTargetPaddingLeft, mTargetPaddingTop, mTargetPaddingRight, mTargetPaddingBottom + targetTop); setTargetOffsetTop(offset, false); }
@Override public void onAnimationEnd(Animation animation) { mBaseRefreshView.stop(); mCurrentOffsetTop = mTarget.getTop(); }
@Override public boolean onTouchEvent(@NonNull MotionEvent ev) { if (!mIsBeingDragged) { return super.onTouchEvent(ev); } final int action = MotionEventCompat.getActionMasked(ev); switch (action) { case MotionEvent.ACTION_MOVE: { final int pointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId); if (pointerIndex < 0) { return false; } final float y = MotionEventCompat.getY(ev, pointerIndex); final float yDiff = y - mInitialMotionY; final float scrollTop = yDiff * DRAG_RATE; mCurrentDragPercent = scrollTop / mTotalDragDistance; if (mCurrentDragPercent < 0) { return false; } float boundedDragPercent = Math.min(1f, Math.abs(mCurrentDragPercent)); float extraOS = Math.abs(scrollTop) - mTotalDragDistance; float slingshotDist = mTotalDragDistance; float tensionSlingshotPercent = Math.max(0, Math.min(extraOS, slingshotDist * 2) / slingshotDist); float tensionPercent = (float) ((tensionSlingshotPercent / 4) - Math.pow((tensionSlingshotPercent / 4), 2)) * 2f; float extraMove = (slingshotDist) * tensionPercent / 2; int targetY = (int) ((slingshotDist * boundedDragPercent) + extraMove); mBaseRefreshView.setPercent(mCurrentDragPercent, true); setTargetOffsetTop(targetY - mCurrentOffsetTop, true); break; } case MotionEventCompat.ACTION_POINTER_DOWN: final int index = MotionEventCompat.getActionIndex(ev); mActivePointerId = MotionEventCompat.getPointerId(ev, index); break; case MotionEventCompat.ACTION_POINTER_UP: onSecondaryPointerUp(ev); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: { if (mActivePointerId == INVALID_POINTER) { return false; } final int pointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId); final float y = MotionEventCompat.getY(ev, pointerIndex); final float overScrollTop = (y - mInitialMotionY) * DRAG_RATE; mIsBeingDragged = false; if (overScrollTop > mTotalDragDistance) { setRefreshing(true, true); } else { mRefreshing = false; animateOffsetToStartPosition(); } mActivePointerId = INVALID_POINTER; return false; } } return true; }