| Index: third_party/android_swipe_refresh/java/src/org/chromium/third_party/android/swiperefresh/SwipeRefreshLayout.java
|
| diff --git a/third_party/android_swipe_refresh/java/src/chromium/third_party/android/swiperefresh/SwipeRefreshLayout.java b/third_party/android_swipe_refresh/java/src/org/chromium/third_party/android/swiperefresh/SwipeRefreshLayout.java
|
| similarity index 61%
|
| rename from third_party/android_swipe_refresh/java/src/chromium/third_party/android/swiperefresh/SwipeRefreshLayout.java
|
| rename to third_party/android_swipe_refresh/java/src/org/chromium/third_party/android/swiperefresh/SwipeRefreshLayout.java
|
| index dfd4cc2ec7e66c110cd886b5734253af8a8438f2..eed8d7763eecd3bcb1a76b5ffd8a1a09ff4d4d76 100644
|
| --- a/third_party/android_swipe_refresh/java/src/chromium/third_party/android/swiperefresh/SwipeRefreshLayout.java
|
| +++ b/third_party/android_swipe_refresh/java/src/org/chromium/third_party/android/swiperefresh/SwipeRefreshLayout.java
|
| @@ -19,8 +19,6 @@ package org.chromium.third_party.android.swiperefresh;
|
| import android.content.Context;
|
| import android.content.res.Resources;
|
| import android.content.res.TypedArray;
|
| -import android.support.v4.view.MotionEventCompat;
|
| -import android.support.v4.view.ViewCompat;
|
| import android.util.AttributeSet;
|
| import android.util.DisplayMetrics;
|
| import android.util.Log;
|
| @@ -70,7 +68,6 @@ public class SwipeRefreshLayout extends ViewGroup {
|
| private static final int CIRCLE_DIAMETER_LARGE = 56;
|
|
|
| private static final float DECELERATE_INTERPOLATION_FACTOR = 2f;
|
| - private static final int INVALID_POINTER = -1;
|
| private static final float DRAG_RATE = .5f;
|
|
|
| // Max amount of circle that can be filled by progress during swipe gesture,
|
| @@ -90,10 +87,8 @@ public class SwipeRefreshLayout extends ViewGroup {
|
| // Default offset in dips from the top of the view to where the progress spinner should stop
|
| private static final int DEFAULT_CIRCLE_TARGET = 64;
|
|
|
| - private View mTarget; // the target of the gesture
|
| private OnRefreshListener mListener;
|
| private boolean mRefreshing = false;
|
| - private int mTouchSlop;
|
| private float mTotalDragDistance = -1;
|
| private int mMediumAnimationDuration;
|
| private int mCurrentTargetOffsetTop;
|
| @@ -102,7 +97,6 @@ public class SwipeRefreshLayout extends ViewGroup {
|
|
|
| private float mInitialMotionY;
|
| private boolean mIsBeingDragged;
|
| - private int mActivePointerId = INVALID_POINTER;
|
| // Whether this item is scaled up rather than clipped
|
| private boolean mScale;
|
|
|
| @@ -135,6 +129,8 @@ public class SwipeRefreshLayout extends ViewGroup {
|
|
|
| private Animation mScaleDownToStartAnimation;
|
|
|
| + private Animation.AnimationListener mCancelAnimationListener;
|
| +
|
| private float mSpinnerFinalOffset;
|
|
|
| private boolean mNotify;
|
| @@ -167,21 +163,19 @@ public class SwipeRefreshLayout extends ViewGroup {
|
| }
|
| }
|
| } else {
|
| - mProgress.stop();
|
| - mCircleView.setVisibility(View.GONE);
|
| - setColorViewAlpha(MAX_ALPHA);
|
| - // Return the circle to its start position
|
| - if (mScale) {
|
| - setAnimationProgress(0 /* animation complete and view is hidden */);
|
| - } else {
|
| - setTargetOffsetTopAndBottom(mOriginalOffsetTop - mCurrentTargetOffsetTop,
|
| - true /* requires update */);
|
| - }
|
| + reset();
|
| }
|
| mCurrentTargetOffsetTop = mCircleView.getTop();
|
| }
|
| };
|
|
|
| + // Chrome-specific additions.
|
| + private float mTotalMotionY;
|
| + // Minimum number of pull updates necessary to trigger a refresh.
|
| + private static int MIN_PULLS_TO_ACTIVATE = 3;
|
| + // Multiplier for the default top offset relative to the size of the progress spinner.
|
| + private static final float DEFAULT_OFFSET_TOP_MULTIPLIER = 1.05f;
|
| +
|
| private void setColorViewAlpha(int targetAlpha) {
|
| mCircleView.getBackground().setAlpha(targetAlpha);
|
| mProgress.setAlpha(targetAlpha);
|
| @@ -267,8 +261,6 @@ public class SwipeRefreshLayout extends ViewGroup {
|
| public SwipeRefreshLayout(Context context, AttributeSet attrs) {
|
| super(context, attrs);
|
|
|
| - mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
|
| -
|
| mMediumAnimationDuration = getResources().getInteger(
|
| android.R.integer.config_mediumAnimTime);
|
|
|
| @@ -284,7 +276,7 @@ public class SwipeRefreshLayout extends ViewGroup {
|
| mCircleHeight = (int) (CIRCLE_DIAMETER * metrics.density);
|
|
|
| createProgressView();
|
| - ViewCompat.setChildrenDrawingOrderEnabled(this, true);
|
| + setChildrenDrawingOrderEnabled(true);
|
| // the absolute offset has to take into account that the circle starts at an offset
|
| mSpinnerFinalOffset = DEFAULT_CIRCLE_TARGET * metrics.density;
|
| mTotalDragDistance = mSpinnerFinalOffset;
|
| @@ -362,13 +354,15 @@ public class SwipeRefreshLayout extends ViewGroup {
|
| // Don't adjust the alpha during appearance otherwise.
|
| mProgress.setAlpha(MAX_ALPHA);
|
| }
|
| - mScaleAnimation = new Animation() {
|
| - @Override
|
| - public void applyTransformation(float interpolatedTime, Transformation t) {
|
| - setAnimationProgress(interpolatedTime);
|
| - }
|
| - };
|
| - mScaleAnimation.setDuration(mMediumAnimationDuration);
|
| + if (mScaleAnimation == null) {
|
| + mScaleAnimation = new Animation() {
|
| + @Override
|
| + public void applyTransformation(float interpolatedTime, Transformation t) {
|
| + setAnimationProgress(interpolatedTime);
|
| + }
|
| + };
|
| + mScaleAnimation.setDuration(mMediumAnimationDuration);
|
| + }
|
| if (listener != null) {
|
| mCircleView.setAnimationListener(listener);
|
| }
|
| @@ -384,15 +378,14 @@ public class SwipeRefreshLayout extends ViewGroup {
|
| if (isAlphaUsedForScale()) {
|
| setColorViewAlpha((int) (progress * MAX_ALPHA));
|
| } else {
|
| - ViewCompat.setScaleX(mCircleView, progress);
|
| - ViewCompat.setScaleY(mCircleView, progress);
|
| + mCircleView.setScaleX(progress);
|
| + mCircleView.setScaleY(progress);
|
| }
|
| }
|
|
|
| private void setRefreshing(boolean refreshing, final boolean notify) {
|
| if (mRefreshing != refreshing) {
|
| mNotify = notify;
|
| - ensureTarget();
|
| mRefreshing = refreshing;
|
| if (mRefreshing) {
|
| animateOffsetToCorrectPosition(mCurrentTargetOffsetTop, mRefreshListener);
|
| @@ -403,13 +396,15 @@ public class SwipeRefreshLayout extends ViewGroup {
|
| }
|
|
|
| private void startScaleDownAnimation(Animation.AnimationListener listener) {
|
| - mScaleDownAnimation = new Animation() {
|
| - @Override
|
| - public void applyTransformation(float interpolatedTime, Transformation t) {
|
| - setAnimationProgress(1 - interpolatedTime);
|
| - }
|
| - };
|
| - mScaleDownAnimation.setDuration(SCALE_DOWN_DURATION);
|
| + if (mScaleDownAnimation == null) {
|
| + mScaleDownAnimation = new Animation() {
|
| + @Override
|
| + public void applyTransformation(float interpolatedTime, Transformation t) {
|
| + setAnimationProgress(1 - interpolatedTime);
|
| + }
|
| + };
|
| + mScaleDownAnimation.setDuration(SCALE_DOWN_DURATION);
|
| + }
|
| mCircleView.setAnimationListener(listener);
|
| mCircleView.clearAnimation();
|
| mCircleView.startAnimation(mScaleDownAnimation);
|
| @@ -487,7 +482,6 @@ public class SwipeRefreshLayout extends ViewGroup {
|
| * @param colors
|
| */
|
| public void setColorSchemeColors(int... colors) {
|
| - ensureTarget();
|
| mProgress.setColorSchemeColors(colors);
|
| }
|
|
|
| @@ -499,20 +493,6 @@ public class SwipeRefreshLayout extends ViewGroup {
|
| return mRefreshing;
|
| }
|
|
|
| - private void ensureTarget() {
|
| - // Don't bother getting the parent height if the parent hasn't been laid
|
| - // out yet.
|
| - if (mTarget == null) {
|
| - for (int i = 0; i < getChildCount(); i++) {
|
| - View child = getChildAt(i);
|
| - if (!child.equals(mCircleView)) {
|
| - mTarget = child;
|
| - break;
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| /**
|
| * Set the distance to trigger a sync in dips
|
| *
|
| @@ -525,22 +505,9 @@ public class SwipeRefreshLayout extends ViewGroup {
|
| @Override
|
| protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
| final int width = getMeasuredWidth();
|
| - final int height = getMeasuredHeight();
|
| if (getChildCount() == 0) {
|
| return;
|
| }
|
| - if (mTarget == null) {
|
| - ensureTarget();
|
| - }
|
| - if (mTarget == null) {
|
| - return;
|
| - }
|
| - final View child = mTarget;
|
| - final int childLeft = getPaddingLeft();
|
| - final int childTop = getPaddingTop();
|
| - final int childWidth = width - getPaddingLeft() - getPaddingRight();
|
| - final int childHeight = height - getPaddingTop() - getPaddingBottom();
|
| - child.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
|
| int circleWidth = mCircleView.getMeasuredWidth();
|
| int circleHeight = mCircleView.getMeasuredHeight();
|
| mCircleView.layout((width / 2 - circleWidth / 2), mCurrentTargetOffsetTop,
|
| @@ -550,21 +517,12 @@ public class SwipeRefreshLayout extends ViewGroup {
|
| @Override
|
| public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
| super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
| - if (mTarget == null) {
|
| - ensureTarget();
|
| - }
|
| - if (mTarget == null) {
|
| - return;
|
| - }
|
| - mTarget.measure(MeasureSpec.makeMeasureSpec(
|
| - getMeasuredWidth() - getPaddingLeft() - getPaddingRight(),
|
| - MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(
|
| - getMeasuredHeight() - getPaddingTop() - getPaddingBottom(), MeasureSpec.EXACTLY));
|
| mCircleView.measure(MeasureSpec.makeMeasureSpec(mCircleWidth, MeasureSpec.EXACTLY),
|
| MeasureSpec.makeMeasureSpec(mCircleHeight, MeasureSpec.EXACTLY));
|
| if (!mUsingCustomStart && !mOriginalOffsetCalculated) {
|
| mOriginalOffsetCalculated = true;
|
| - mCurrentTargetOffsetTop = mOriginalOffsetTop = -mCircleView.getMeasuredHeight();
|
| + mCurrentTargetOffsetTop = mOriginalOffsetTop =
|
| + (int) (-mCircleView.getMeasuredHeight() * DEFAULT_OFFSET_TOP_MULTIPLIER);
|
| }
|
| mCircleViewIndex = -1;
|
| // Get the index of the circleview.
|
| @@ -577,237 +535,146 @@ public class SwipeRefreshLayout extends ViewGroup {
|
| }
|
|
|
| /**
|
| - * @return Whether it is possible for the child view of this layout to
|
| - * scroll up. Override this if the child view is a custom view.
|
| + * Start the pull effect. If the effect is disabled or a refresh animation
|
| + * is currently active, the request will be ignored.
|
| + * @return whether a new pull sequence has started.
|
| */
|
| - public boolean canChildScrollUp() {
|
| - if (android.os.Build.VERSION.SDK_INT < 14) {
|
| - if (mTarget instanceof AbsListView) {
|
| - final AbsListView absListView = (AbsListView) mTarget;
|
| - return absListView.getChildCount() > 0
|
| - && (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0)
|
| - .getTop() < absListView.getPaddingTop());
|
| - } else {
|
| - return mTarget.getScrollY() > 0;
|
| - }
|
| - } else {
|
| - return ViewCompat.canScrollVertically(mTarget, -1);
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public boolean onInterceptTouchEvent(MotionEvent ev) {
|
| - ensureTarget();
|
| -
|
| - final int action = MotionEventCompat.getActionMasked(ev);
|
| -
|
| - if (mReturningToStart && action == MotionEvent.ACTION_DOWN) {
|
| - mReturningToStart = false;
|
| - }
|
| -
|
| - if (!isEnabled() || mReturningToStart || canChildScrollUp() || mRefreshing) {
|
| - // Fail fast if we're not in a state where a swipe is possible
|
| - return false;
|
| - }
|
| -
|
| - switch (action) {
|
| - case MotionEvent.ACTION_DOWN:
|
| - setTargetOffsetTopAndBottom(mOriginalOffsetTop - mCircleView.getTop(), true);
|
| - mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
|
| - mIsBeingDragged = false;
|
| - final float initialMotionY = getMotionEventY(ev, mActivePointerId);
|
| - if (initialMotionY == -1) {
|
| - return false;
|
| - }
|
| - mInitialMotionY = initialMotionY;
|
| -
|
| - case MotionEvent.ACTION_MOVE:
|
| - if (mActivePointerId == INVALID_POINTER) {
|
| - Log.e(LOG_TAG, "Got ACTION_MOVE event but don't have an active pointer id.");
|
| - return false;
|
| - }
|
| -
|
| - final float y = getMotionEventY(ev, mActivePointerId);
|
| - if (y == -1) {
|
| - return false;
|
| - }
|
| - final float yDiff = y - mInitialMotionY;
|
| - if (yDiff > mTouchSlop && !mIsBeingDragged) {
|
| - mIsBeingDragged = true;
|
| - mProgress.setAlpha(STARTING_PROGRESS_ALPHA);
|
| - }
|
| - break;
|
| -
|
| - case MotionEventCompat.ACTION_POINTER_UP:
|
| - onSecondaryPointerUp(ev);
|
| - break;
|
| -
|
| - case MotionEvent.ACTION_UP:
|
| - case MotionEvent.ACTION_CANCEL:
|
| - mIsBeingDragged = false;
|
| - mActivePointerId = INVALID_POINTER;
|
| - break;
|
| - }
|
| -
|
| - return mIsBeingDragged;
|
| + public boolean start() {
|
| + if (!isEnabled()) return false;
|
| + if (mRefreshing) return false;
|
| + mCircleView.clearAnimation();
|
| + mProgress.stop();
|
| + // See ACTION_DOWN handling in {@link #onTouchEvent(...)}.
|
| + setTargetOffsetTopAndBottom(mOriginalOffsetTop - mCircleView.getTop(), true);
|
| + mTotalMotionY = 0;
|
| + mIsBeingDragged = true;
|
| + mProgress.setAlpha(STARTING_PROGRESS_ALPHA);
|
| + return true;
|
| }
|
|
|
| - private float getMotionEventY(MotionEvent ev, int activePointerId) {
|
| - final int index = MotionEventCompat.findPointerIndex(ev, activePointerId);
|
| - if (index < 0) {
|
| - return -1;
|
| + /**
|
| + * Apply a pull impulse to the effect. If the effect is disabled or has yet
|
| + * to start, the pull will be ignored.
|
| + * @param delta the magnitude of the pull.
|
| + */
|
| + public void pull(float delta) {
|
| + if (!isEnabled()) return;
|
| + if (!mIsBeingDragged) return;
|
| + delta *= DRAG_RATE;
|
| + float max_delta = mTotalDragDistance / MIN_PULLS_TO_ACTIVATE;
|
| + delta = Math.max(-max_delta, Math.min(max_delta, delta));
|
| + mTotalMotionY += delta;
|
| +
|
| + // See ACTION_MOVE handling in {@link #onTouchEvent(...)}.
|
| + final float overscrollTop = mTotalMotionY;
|
| + mProgress.showArrow(true);
|
| + float originalDragPercent = overscrollTop / mTotalDragDistance;
|
| + if (originalDragPercent < 0) return;
|
| + float dragPercent = Math.min(1f, Math.abs(originalDragPercent));
|
| + float adjustedPercent = (float) Math.max(dragPercent - .4, 0) * 5 / 3;
|
| + float extraOS = Math.abs(overscrollTop) - mTotalDragDistance;
|
| + float slingshotDist = mUsingCustomStart ? mSpinnerFinalOffset
|
| + - mOriginalOffsetTop : mSpinnerFinalOffset;
|
| + 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 = mOriginalOffsetTop
|
| + + (int) ((slingshotDist * dragPercent) + extraMove);
|
| + // where 1.0f is a full circle
|
| + if (mCircleView.getVisibility() != View.VISIBLE) {
|
| + mCircleView.setVisibility(View.VISIBLE);
|
| + }
|
| + if (!mScale) {
|
| + mCircleView.setScaleX(1f);
|
| + mCircleView.setScaleY(1f);
|
| + }
|
| + if (overscrollTop < mTotalDragDistance) {
|
| + if (mScale) {
|
| + setAnimationProgress(overscrollTop / mTotalDragDistance);
|
| + }
|
| }
|
| - return MotionEventCompat.getY(ev, index);
|
| - }
|
| + float strokeStart = (float) (adjustedPercent * .8f);
|
| + mProgress.setStartEndTrim(0f, Math.min(MAX_PROGRESS_ANGLE, strokeStart));
|
| + mProgress.setArrowScale(Math.min(1f, adjustedPercent));
|
|
|
| - @Override
|
| - public void requestDisallowInterceptTouchEvent(boolean b) {
|
| - // Nope.
|
| - }
|
| + float alphaStrength = Math.max(0f, Math.min(1f, (dragPercent - .9f) / .1f));
|
| + int alpha = STARTING_PROGRESS_ALPHA;
|
| + alpha += (int) (alphaStrength * (MAX_ALPHA - STARTING_PROGRESS_ALPHA));
|
| + mProgress.setAlpha(alpha);
|
|
|
| - private boolean isAnimationRunning(Animation animation) {
|
| - return animation != null && animation.hasStarted() && !animation.hasEnded();
|
| + float rotation = (-0.25f + .4f * adjustedPercent + tensionPercent * 2) * .5f;
|
| + mProgress.setProgressRotation(rotation);
|
| + setTargetOffsetTopAndBottom(targetY - mCurrentTargetOffsetTop,
|
| + true /* requires update */);
|
| }
|
|
|
| - @Override
|
| - public boolean onTouchEvent(MotionEvent ev) {
|
| - final int action = MotionEventCompat.getActionMasked(ev);
|
| -
|
| - if (mReturningToStart && action == MotionEvent.ACTION_DOWN) {
|
| - mReturningToStart = false;
|
| - }
|
| -
|
| - if (!isEnabled() || mReturningToStart || canChildScrollUp()) {
|
| - // Fail fast if we're not in a state where a swipe is possible
|
| - return false;
|
| + /**
|
| + * Release the active pull. If no pull has started, the release will be
|
| + * ignored. If the pull was sufficiently large, the refresh sequence will
|
| + * be initiated.
|
| + * @param allowRefresh whether to allow a sufficiently large pull to trigger
|
| + * the refresh action and animation sequence.
|
| + */
|
| + public void release(boolean allowRefresh) {
|
| + if (!mIsBeingDragged) return;
|
| +
|
| + // See ACTION_UP handling in {@link #onTouchEvent(...)}.
|
| + mIsBeingDragged = false;
|
| + final float overscrollTop = mTotalMotionY;
|
| + if (isEnabled() && allowRefresh && overscrollTop > mTotalDragDistance) {
|
| + setRefreshing(true, true /* notify */);
|
| + return;
|
| }
|
| + // cancel refresh
|
| + mRefreshing = false;
|
| + mProgress.setStartEndTrim(0f, 0f);
|
| + Animation.AnimationListener listener = null;
|
| + if (!mScale) {
|
| + if (mCancelAnimationListener == null) {
|
| + mCancelAnimationListener = new Animation.AnimationListener() {
|
|
|
| - switch (action) {
|
| - case MotionEvent.ACTION_DOWN:
|
| - mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
|
| - mIsBeingDragged = false;
|
| - break;
|
| -
|
| - case MotionEvent.ACTION_MOVE: {
|
| - final int pointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId);
|
| - if (pointerIndex < 0) {
|
| - Log.e(LOG_TAG, "Got ACTION_MOVE event but have an invalid active pointer id.");
|
| - return false;
|
| - }
|
| -
|
| - final float y = MotionEventCompat.getY(ev, pointerIndex);
|
| - final float overscrollTop = (y - mInitialMotionY) * DRAG_RATE;
|
| - if (mIsBeingDragged) {
|
| - mProgress.showArrow(true);
|
| - float originalDragPercent = overscrollTop / mTotalDragDistance;
|
| - if (originalDragPercent < 0) {
|
| - return false;
|
| - }
|
| - float dragPercent = Math.min(1f, Math.abs(originalDragPercent));
|
| - float adjustedPercent = (float) Math.max(dragPercent - .4, 0) * 5 / 3;
|
| - float extraOS = Math.abs(overscrollTop) - mTotalDragDistance;
|
| - float slingshotDist = mUsingCustomStart ? mSpinnerFinalOffset
|
| - - mOriginalOffsetTop : mSpinnerFinalOffset;
|
| - 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 = mOriginalOffsetTop
|
| - + (int) ((slingshotDist * dragPercent) + extraMove);
|
| - // where 1.0f is a full circle
|
| - if (mCircleView.getVisibility() != View.VISIBLE) {
|
| - mCircleView.setVisibility(View.VISIBLE);
|
| + @Override
|
| + public void onAnimationStart(Animation animation) {
|
| }
|
| - if (!mScale) {
|
| - ViewCompat.setScaleX(mCircleView, 1f);
|
| - ViewCompat.setScaleY(mCircleView, 1f);
|
| - }
|
| - if (overscrollTop < mTotalDragDistance) {
|
| - if (mScale) {
|
| - setAnimationProgress(overscrollTop / mTotalDragDistance);
|
| - }
|
| - if (mProgress.getAlpha() > STARTING_PROGRESS_ALPHA
|
| - && !isAnimationRunning(mAlphaStartAnimation)) {
|
| - // Animate the alpha
|
| - startProgressAlphaStartAnimation();
|
| - }
|
| - float strokeStart = (float) (adjustedPercent * .8f);
|
| - mProgress.setStartEndTrim(0f, Math.min(MAX_PROGRESS_ANGLE, strokeStart));
|
| - mProgress.setArrowScale(Math.min(1f, adjustedPercent));
|
| - } else {
|
| - if (mProgress.getAlpha() < MAX_ALPHA
|
| - && !isAnimationRunning(mAlphaMaxAnimation)) {
|
| - // Animate the alpha
|
| - startProgressAlphaMaxAnimation();
|
| +
|
| + @Override
|
| + public void onAnimationEnd(Animation animation) {
|
| + if (!mScale) {
|
| + startScaleDownAnimation(mRefreshListener);
|
| }
|
| }
|
| - float rotation = (-0.25f + .4f * adjustedPercent + tensionPercent * 2) * .5f;
|
| - mProgress.setProgressRotation(rotation);
|
| - setTargetOffsetTopAndBottom(targetY - mCurrentTargetOffsetTop,
|
| - true /* requires update */);
|
| - }
|
| - 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) {
|
| - if (action == MotionEvent.ACTION_UP) {
|
| - Log.e(LOG_TAG, "Got ACTION_UP event but don't have an active pointer id.");
|
| - }
|
| - 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 /* notify */);
|
| - } else {
|
| - // cancel refresh
|
| - mRefreshing = false;
|
| - mProgress.setStartEndTrim(0f, 0f);
|
| - Animation.AnimationListener listener = null;
|
| - if (!mScale) {
|
| - listener = new Animation.AnimationListener() {
|
| -
|
| - @Override
|
| - public void onAnimationStart(Animation animation) {
|
| - }
|
| -
|
| - @Override
|
| - public void onAnimationEnd(Animation animation) {
|
| - if (!mScale) {
|
| - startScaleDownAnimation(null);
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public void onAnimationRepeat(Animation animation) {
|
| - }
|
| -
|
| - };
|
| + @Override
|
| + public void onAnimationRepeat(Animation animation) {
|
| }
|
| - animateOffsetToStartPosition(mCurrentTargetOffsetTop, listener);
|
| - mProgress.showArrow(false);
|
| - }
|
| - mActivePointerId = INVALID_POINTER;
|
| - return false;
|
| + };
|
| }
|
| + listener = mCancelAnimationListener;
|
| }
|
| + animateOffsetToStartPosition(mCurrentTargetOffsetTop, listener);
|
| + mProgress.showArrow(false);
|
| + }
|
|
|
| - return true;
|
| + /**
|
| + * Reset the effect, clearing any active animations.
|
| + */
|
| + public void reset() {
|
| + mIsBeingDragged = false;
|
| + setRefreshing(false, false /* notify */);
|
| + mProgress.stop();
|
| + mCircleView.setVisibility(View.GONE);
|
| + setColorViewAlpha(MAX_ALPHA);
|
| + // Return the circle to its start position
|
| + if (mScale) {
|
| + setAnimationProgress(0 /* animation complete and view is hidden */);
|
| + } else {
|
| + setTargetOffsetTopAndBottom(mOriginalOffsetTop - mCurrentTargetOffsetTop,
|
| + true /* requires update */);
|
| + }
|
| + mCurrentTargetOffsetTop = mCircleView.getTop();
|
| }
|
|
|
| private void animateOffsetToCorrectPosition(int from, AnimationListener listener) {
|
| @@ -875,17 +742,19 @@ public class SwipeRefreshLayout extends ViewGroup {
|
| if (isAlphaUsedForScale()) {
|
| mStartingScale = mProgress.getAlpha();
|
| } else {
|
| - mStartingScale = ViewCompat.getScaleX(mCircleView);
|
| + mStartingScale = mCircleView.getScaleX();
|
| + }
|
| + if (mScaleDownToStartAnimation == null) {
|
| + mScaleDownToStartAnimation = new Animation() {
|
| + @Override
|
| + public void applyTransformation(float interpolatedTime, Transformation t) {
|
| + float targetScale = (mStartingScale + (-mStartingScale * interpolatedTime));
|
| + setAnimationProgress(targetScale);
|
| + moveToStart(interpolatedTime);
|
| + }
|
| + };
|
| + mScaleDownToStartAnimation.setDuration(SCALE_DOWN_DURATION);
|
| }
|
| - mScaleDownToStartAnimation = new Animation() {
|
| - @Override
|
| - public void applyTransformation(float interpolatedTime, Transformation t) {
|
| - float targetScale = (mStartingScale + (-mStartingScale * interpolatedTime));
|
| - setAnimationProgress(targetScale);
|
| - moveToStart(interpolatedTime);
|
| - }
|
| - };
|
| - mScaleDownToStartAnimation.setDuration(SCALE_DOWN_DURATION);
|
| if (listener != null) {
|
| mCircleView.setAnimationListener(listener);
|
| }
|
| @@ -902,17 +771,6 @@ public class SwipeRefreshLayout extends ViewGroup {
|
| }
|
| }
|
|
|
| - private void onSecondaryPointerUp(MotionEvent ev) {
|
| - final int pointerIndex = MotionEventCompat.getActionIndex(ev);
|
| - final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);
|
| - if (pointerId == mActivePointerId) {
|
| - // This was our active pointer going up. Choose a new
|
| - // active pointer and adjust accordingly.
|
| - final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
|
| - mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);
|
| - }
|
| - }
|
| -
|
| /**
|
| * Classes that wish to be notified when the swipe gesture correctly
|
| * triggers a refresh should implement this interface.
|
|
|