Index: third_party/android_swipe_refresh/java/src/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/chromium/third_party/android/swiperefresh/SwipeRefreshLayout.java |
deleted file mode 100644 |
index dfd4cc2ec7e66c110cd886b5734253af8a8438f2..0000000000000000000000000000000000000000 |
--- a/third_party/android_swipe_refresh/java/src/chromium/third_party/android/swiperefresh/SwipeRefreshLayout.java |
+++ /dev/null |
@@ -1,923 +0,0 @@ |
-/* |
- * Copyright (C) 2013 The Android Open Source Project |
- * |
- * Licensed under the Apache License, Version 2.0 (the "License"); |
- * you may not use this file except in compliance with the License. |
- * You may obtain a copy of the License at |
- * |
- * http://www.apache.org/licenses/LICENSE-2.0 |
- * |
- * Unless required by applicable law or agreed to in writing, software |
- * distributed under the License is distributed on an "AS IS" BASIS, |
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
- * See the License for the specific language governing permissions and |
- * limitations under the License. |
- */ |
- |
-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; |
-import android.view.MotionEvent; |
-import android.view.View; |
-import android.view.ViewConfiguration; |
-import android.view.ViewGroup; |
-import android.view.animation.Animation; |
-import android.view.animation.Animation.AnimationListener; |
-import android.view.animation.DecelerateInterpolator; |
-import android.view.animation.Transformation; |
-import android.widget.AbsListView; |
- |
-/** |
- * The SwipeRefreshLayout should be used whenever the user can refresh the |
- * contents of a view via a vertical swipe gesture. The activity that |
- * instantiates this view should add an OnRefreshListener to be notified |
- * whenever the swipe to refresh gesture is completed. The SwipeRefreshLayout |
- * will notify the listener each and every time the gesture is completed again; |
- * the listener is responsible for correctly determining when to actually |
- * initiate a refresh of its content. If the listener determines there should |
- * not be a refresh, it must call setRefreshing(false) to cancel any visual |
- * indication of a refresh. If an activity wishes to show just the progress |
- * animation, it should call setRefreshing(true). To disable the gesture and |
- * progress animation, call setEnabled(false) on the view. |
- * <p> |
- * This layout should be made the parent of the view that will be refreshed as a |
- * result of the gesture and can only support one direct child. This view will |
- * also be made the target of the gesture and will be forced to match both the |
- * width and the height supplied in this layout. The SwipeRefreshLayout does not |
- * provide accessibility events; instead, a menu item must be provided to allow |
- * refresh of the content wherever this gesture is used. |
- * </p> |
- */ |
-public class SwipeRefreshLayout extends ViewGroup { |
- // Maps to ProgressBar.Large style |
- public static final int LARGE = MaterialProgressDrawable.LARGE; |
- // Maps to ProgressBar default style |
- public static final int DEFAULT = MaterialProgressDrawable.DEFAULT; |
- |
- private static final String LOG_TAG = SwipeRefreshLayout.class.getSimpleName(); |
- |
- private static final int MAX_ALPHA = 255; |
- private static final int STARTING_PROGRESS_ALPHA = (int) (.3f * MAX_ALPHA); |
- |
- private static final int CIRCLE_DIAMETER = 40; |
- 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, |
- // where 1.0 is a full circle |
- private static final float MAX_PROGRESS_ANGLE = .8f; |
- |
- private static final int SCALE_DOWN_DURATION = 150; |
- |
- private static final int ALPHA_ANIMATION_DURATION = 300; |
- |
- private static final int ANIMATE_TO_TRIGGER_DURATION = 200; |
- |
- private static final int ANIMATE_TO_START_DURATION = 200; |
- |
- // Default background for the progress spinner |
- private static final int CIRCLE_BG_LIGHT = 0xFFFAFAFA; |
- // 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; |
- // Whether or not the starting offset has been determined. |
- private boolean mOriginalOffsetCalculated = false; |
- |
- private float mInitialMotionY; |
- private boolean mIsBeingDragged; |
- private int mActivePointerId = INVALID_POINTER; |
- // Whether this item is scaled up rather than clipped |
- private boolean mScale; |
- |
- // Target is returning to its start offset because it was cancelled or a |
- // refresh was triggered. |
- private boolean mReturningToStart; |
- private final DecelerateInterpolator mDecelerateInterpolator; |
- private static final int[] LAYOUT_ATTRS = new int[] { |
- android.R.attr.enabled |
- }; |
- |
- private CircleImageView mCircleView; |
- private int mCircleViewIndex = -1; |
- |
- protected int mFrom; |
- |
- private float mStartingScale; |
- |
- protected int mOriginalOffsetTop; |
- |
- private MaterialProgressDrawable mProgress; |
- |
- private Animation mScaleAnimation; |
- |
- private Animation mScaleDownAnimation; |
- |
- private Animation mAlphaStartAnimation; |
- |
- private Animation mAlphaMaxAnimation; |
- |
- private Animation mScaleDownToStartAnimation; |
- |
- private float mSpinnerFinalOffset; |
- |
- private boolean mNotify; |
- |
- private int mCircleWidth; |
- |
- private int mCircleHeight; |
- |
- // Whether the client has set a custom starting position; |
- private boolean mUsingCustomStart; |
- |
- private Animation.AnimationListener mRefreshListener = new Animation.AnimationListener() { |
- @Override |
- public void onAnimationStart(Animation animation) { |
- } |
- |
- @Override |
- public void onAnimationRepeat(Animation animation) { |
- } |
- |
- @Override |
- public void onAnimationEnd(Animation animation) { |
- if (mRefreshing) { |
- // Make sure the progress view is fully visible |
- mProgress.setAlpha(MAX_ALPHA); |
- mProgress.start(); |
- if (mNotify) { |
- if (mListener != null) { |
- mListener.onRefresh(); |
- } |
- } |
- } 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 */); |
- } |
- } |
- mCurrentTargetOffsetTop = mCircleView.getTop(); |
- } |
- }; |
- |
- private void setColorViewAlpha(int targetAlpha) { |
- mCircleView.getBackground().setAlpha(targetAlpha); |
- mProgress.setAlpha(targetAlpha); |
- } |
- |
- /** |
- * The refresh indicator starting and resting position is always positioned |
- * near the top of the refreshing content. This position is a consistent |
- * location, but can be adjusted in either direction based on whether or not |
- * there is a toolbar or actionbar present. |
- * |
- * @param scale Set to true if there is no view at a higher z-order than |
- * where the progress spinner is set to appear. |
- * @param start The offset in pixels from the top of this view at which the |
- * progress spinner should appear. |
- * @param end The offset in pixels from the top of this view at which the |
- * progress spinner should come to rest after a successful swipe |
- * gesture. |
- */ |
- public void setProgressViewOffset(boolean scale, int start, int end) { |
- mScale = scale; |
- mCircleView.setVisibility(View.GONE); |
- mOriginalOffsetTop = mCurrentTargetOffsetTop = start; |
- mSpinnerFinalOffset = end; |
- mUsingCustomStart = true; |
- mCircleView.invalidate(); |
- } |
- |
- /** |
- * The refresh indicator resting position is always positioned near the top |
- * of the refreshing content. This position is a consistent location, but |
- * can be adjusted in either direction based on whether or not there is a |
- * toolbar or actionbar present. |
- * |
- * @param scale Set to true if there is no view at a higher z-order than |
- * where the progress spinner is set to appear. |
- * @param end The offset in pixels from the top of this view at which the |
- * progress spinner should come to rest after a successful swipe |
- * gesture. |
- */ |
- public void setProgressViewEndTarget(boolean scale, int end) { |
- mSpinnerFinalOffset = end; |
- mScale = scale; |
- mCircleView.invalidate(); |
- } |
- |
- /** |
- * One of DEFAULT, or LARGE. |
- */ |
- public void setSize(int size) { |
- if (size != MaterialProgressDrawable.LARGE && size != MaterialProgressDrawable.DEFAULT) { |
- return; |
- } |
- final DisplayMetrics metrics = getResources().getDisplayMetrics(); |
- if (size == MaterialProgressDrawable.LARGE) { |
- mCircleHeight = mCircleWidth = (int) (CIRCLE_DIAMETER_LARGE * metrics.density); |
- } else { |
- mCircleHeight = mCircleWidth = (int) (CIRCLE_DIAMETER * metrics.density); |
- } |
- // force the bounds of the progress circle inside the circle view to |
- // update by setting it to null before updating its size and then |
- // re-setting it |
- mCircleView.setImageDrawable(null); |
- mProgress.updateSizes(size); |
- mCircleView.setImageDrawable(mProgress); |
- } |
- |
- /** |
- * Simple constructor to use when creating a SwipeRefreshLayout from code. |
- * |
- * @param context |
- */ |
- public SwipeRefreshLayout(Context context) { |
- this(context, null); |
- } |
- |
- /** |
- * Constructor that is called when inflating SwipeRefreshLayout from XML. |
- * |
- * @param context |
- * @param attrs |
- */ |
- public SwipeRefreshLayout(Context context, AttributeSet attrs) { |
- super(context, attrs); |
- |
- mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); |
- |
- mMediumAnimationDuration = getResources().getInteger( |
- android.R.integer.config_mediumAnimTime); |
- |
- setWillNotDraw(false); |
- mDecelerateInterpolator = new DecelerateInterpolator(DECELERATE_INTERPOLATION_FACTOR); |
- |
- final TypedArray a = context.obtainStyledAttributes(attrs, LAYOUT_ATTRS); |
- setEnabled(a.getBoolean(0, true)); |
- a.recycle(); |
- |
- final DisplayMetrics metrics = getResources().getDisplayMetrics(); |
- mCircleWidth = (int) (CIRCLE_DIAMETER * metrics.density); |
- mCircleHeight = (int) (CIRCLE_DIAMETER * metrics.density); |
- |
- createProgressView(); |
- ViewCompat.setChildrenDrawingOrderEnabled(this, true); |
- // the absolute offset has to take into account that the circle starts at an offset |
- mSpinnerFinalOffset = DEFAULT_CIRCLE_TARGET * metrics.density; |
- mTotalDragDistance = mSpinnerFinalOffset; |
- } |
- |
- protected int getChildDrawingOrder(int childCount, int i) { |
- if (mCircleViewIndex < 0) { |
- return i; |
- } else if (i == childCount - 1) { |
- // Draw the selected child last |
- return mCircleViewIndex; |
- } else if (i >= mCircleViewIndex) { |
- // Move the children after the selected child earlier one |
- return i + 1; |
- } else { |
- // Keep the children before the selected child the same |
- return i; |
- } |
- } |
- |
- private void createProgressView() { |
- mCircleView = new CircleImageView(getContext(), CIRCLE_BG_LIGHT, CIRCLE_DIAMETER/2); |
- mProgress = new MaterialProgressDrawable(getContext(), this); |
- mProgress.setBackgroundColor(CIRCLE_BG_LIGHT); |
- mCircleView.setImageDrawable(mProgress); |
- mCircleView.setVisibility(View.GONE); |
- addView(mCircleView); |
- } |
- |
- /** |
- * Set the listener to be notified when a refresh is triggered via the swipe |
- * gesture. |
- */ |
- public void setOnRefreshListener(OnRefreshListener listener) { |
- mListener = listener; |
- } |
- |
- /** |
- * Pre API 11, alpha is used to make the progress circle appear instead of scale. |
- */ |
- private boolean isAlphaUsedForScale() { |
- return android.os.Build.VERSION.SDK_INT < 11; |
- } |
- |
- /** |
- * Notify the widget that refresh state has changed. Do not call this when |
- * refresh is triggered by a swipe gesture. |
- * |
- * @param refreshing Whether or not the view should show refresh progress. |
- */ |
- public void setRefreshing(boolean refreshing) { |
- if (refreshing && mRefreshing != refreshing) { |
- // scale and show |
- mRefreshing = refreshing; |
- int endTarget = 0; |
- if (!mUsingCustomStart) { |
- endTarget = (int) (mSpinnerFinalOffset + mOriginalOffsetTop); |
- } else { |
- endTarget = (int) mSpinnerFinalOffset; |
- } |
- setTargetOffsetTopAndBottom(endTarget - mCurrentTargetOffsetTop, |
- true /* requires update */); |
- mNotify = false; |
- startScaleUpAnimation(mRefreshListener); |
- } else { |
- setRefreshing(refreshing, false /* notify */); |
- } |
- } |
- |
- private void startScaleUpAnimation(AnimationListener listener) { |
- mCircleView.setVisibility(View.VISIBLE); |
- if (android.os.Build.VERSION.SDK_INT >= 11) { |
- // Pre API 11, alpha is used in place of scale up to show the |
- // progress circle appearing. |
- // 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 (listener != null) { |
- mCircleView.setAnimationListener(listener); |
- } |
- mCircleView.clearAnimation(); |
- mCircleView.startAnimation(mScaleAnimation); |
- } |
- |
- /** |
- * Pre API 11, this does an alpha animation. |
- * @param progress |
- */ |
- private void setAnimationProgress(float progress) { |
- if (isAlphaUsedForScale()) { |
- setColorViewAlpha((int) (progress * MAX_ALPHA)); |
- } else { |
- ViewCompat.setScaleX(mCircleView, progress); |
- ViewCompat.setScaleY(mCircleView, progress); |
- } |
- } |
- |
- private void setRefreshing(boolean refreshing, final boolean notify) { |
- if (mRefreshing != refreshing) { |
- mNotify = notify; |
- ensureTarget(); |
- mRefreshing = refreshing; |
- if (mRefreshing) { |
- animateOffsetToCorrectPosition(mCurrentTargetOffsetTop, mRefreshListener); |
- } else { |
- startScaleDownAnimation(mRefreshListener); |
- } |
- } |
- } |
- |
- 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); |
- mCircleView.setAnimationListener(listener); |
- mCircleView.clearAnimation(); |
- mCircleView.startAnimation(mScaleDownAnimation); |
- } |
- |
- private void startProgressAlphaStartAnimation() { |
- mAlphaStartAnimation = startAlphaAnimation(mProgress.getAlpha(), STARTING_PROGRESS_ALPHA); |
- } |
- |
- private void startProgressAlphaMaxAnimation() { |
- mAlphaMaxAnimation = startAlphaAnimation(mProgress.getAlpha(), MAX_ALPHA); |
- } |
- |
- private Animation startAlphaAnimation(final int startingAlpha, final int endingAlpha) { |
- // Pre API 11, alpha is used in place of scale. Don't also use it to |
- // show the trigger point. |
- if (mScale && isAlphaUsedForScale()) { |
- return null; |
- } |
- Animation alpha = new Animation() { |
- @Override |
- public void applyTransformation(float interpolatedTime, Transformation t) { |
- mProgress |
- .setAlpha((int) (startingAlpha+ ((endingAlpha - startingAlpha) |
- * interpolatedTime))); |
- } |
- }; |
- alpha.setDuration(ALPHA_ANIMATION_DURATION); |
- // Clear out the previous animation listeners. |
- mCircleView.setAnimationListener(null); |
- mCircleView.clearAnimation(); |
- mCircleView.startAnimation(alpha); |
- return alpha; |
- } |
- |
- /** |
- * Set the background color of the progress spinner disc. |
- * |
- * @param colorRes Resource id of the color. |
- */ |
- public void setProgressBackgroundColor(int colorRes) { |
- mCircleView.setBackgroundColor(colorRes); |
- mProgress.setBackgroundColor(getResources().getColor(colorRes)); |
- } |
- |
- /** |
- * @deprecated Use {@link #setColorSchemeResources(int...)} |
- */ |
- @Deprecated |
- public void setColorScheme(int... colors) { |
- setColorSchemeResources(colors); |
- } |
- |
- /** |
- * Set the color resources used in the progress animation from color resources. |
- * The first color will also be the color of the bar that grows in response |
- * to a user swipe gesture. |
- * |
- * @param colorResIds |
- */ |
- public void setColorSchemeResources(int... colorResIds) { |
- final Resources res = getResources(); |
- int[] colorRes = new int[colorResIds.length]; |
- for (int i = 0; i < colorResIds.length; i++) { |
- colorRes[i] = res.getColor(colorResIds[i]); |
- } |
- setColorSchemeColors(colorRes); |
- } |
- |
- /** |
- * Set the colors used in the progress animation. The first |
- * color will also be the color of the bar that grows in response to a user |
- * swipe gesture. |
- * |
- * @param colors |
- */ |
- public void setColorSchemeColors(int... colors) { |
- ensureTarget(); |
- mProgress.setColorSchemeColors(colors); |
- } |
- |
- /** |
- * @return Whether the SwipeRefreshWidget is actively showing refresh |
- * progress. |
- */ |
- public boolean isRefreshing() { |
- 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 |
- * |
- * @param distance |
- */ |
- public void setDistanceToTriggerSync(int distance) { |
- mTotalDragDistance = distance; |
- } |
- |
- @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, |
- (width / 2 + circleWidth / 2), mCurrentTargetOffsetTop + circleHeight); |
- } |
- |
- @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(); |
- } |
- mCircleViewIndex = -1; |
- // Get the index of the circleview. |
- for (int index = 0; index < getChildCount(); index++) { |
- if (getChildAt(index) == mCircleView) { |
- mCircleViewIndex = index; |
- break; |
- } |
- } |
- } |
- |
- /** |
- * @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. |
- */ |
- 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; |
- } |
- |
- private float getMotionEventY(MotionEvent ev, int activePointerId) { |
- final int index = MotionEventCompat.findPointerIndex(ev, activePointerId); |
- if (index < 0) { |
- return -1; |
- } |
- return MotionEventCompat.getY(ev, index); |
- } |
- |
- @Override |
- public void requestDisallowInterceptTouchEvent(boolean b) { |
- // Nope. |
- } |
- |
- private boolean isAnimationRunning(Animation animation) { |
- return animation != null && animation.hasStarted() && !animation.hasEnded(); |
- } |
- |
- @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; |
- } |
- |
- 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); |
- } |
- 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(); |
- } |
- } |
- 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) { |
- } |
- |
- }; |
- } |
- animateOffsetToStartPosition(mCurrentTargetOffsetTop, listener); |
- mProgress.showArrow(false); |
- } |
- mActivePointerId = INVALID_POINTER; |
- return false; |
- } |
- } |
- |
- return true; |
- } |
- |
- private void animateOffsetToCorrectPosition(int from, AnimationListener listener) { |
- mFrom = from; |
- mAnimateToCorrectPosition.reset(); |
- mAnimateToCorrectPosition.setDuration(ANIMATE_TO_TRIGGER_DURATION); |
- mAnimateToCorrectPosition.setInterpolator(mDecelerateInterpolator); |
- if (listener != null) { |
- mCircleView.setAnimationListener(listener); |
- } |
- mCircleView.clearAnimation(); |
- mCircleView.startAnimation(mAnimateToCorrectPosition); |
- } |
- |
- private void animateOffsetToStartPosition(int from, AnimationListener listener) { |
- if (mScale) { |
- // Scale the item back down |
- startScaleDownReturnToStartAnimation(from, listener); |
- } else { |
- mFrom = from; |
- mAnimateToStartPosition.reset(); |
- mAnimateToStartPosition.setDuration(ANIMATE_TO_START_DURATION); |
- mAnimateToStartPosition.setInterpolator(mDecelerateInterpolator); |
- if (listener != null) { |
- mCircleView.setAnimationListener(listener); |
- } |
- mCircleView.clearAnimation(); |
- mCircleView.startAnimation(mAnimateToStartPosition); |
- } |
- } |
- |
- private final Animation mAnimateToCorrectPosition = new Animation() { |
- @Override |
- public void applyTransformation(float interpolatedTime, Transformation t) { |
- int targetTop = 0; |
- int endTarget = 0; |
- if (!mUsingCustomStart) { |
- endTarget = (int) (mSpinnerFinalOffset - Math.abs(mOriginalOffsetTop)); |
- } else { |
- endTarget = (int) mSpinnerFinalOffset; |
- } |
- targetTop = (mFrom + (int) ((endTarget - mFrom) * interpolatedTime)); |
- int offset = targetTop - mCircleView.getTop(); |
- setTargetOffsetTopAndBottom(offset, false /* requires update */); |
- } |
- }; |
- |
- private void moveToStart(float interpolatedTime) { |
- int targetTop = 0; |
- targetTop = (mFrom + (int) ((mOriginalOffsetTop - mFrom) * interpolatedTime)); |
- int offset = targetTop - mCircleView.getTop(); |
- setTargetOffsetTopAndBottom(offset, false /* requires update */); |
- } |
- |
- private final Animation mAnimateToStartPosition = new Animation() { |
- @Override |
- public void applyTransformation(float interpolatedTime, Transformation t) { |
- moveToStart(interpolatedTime); |
- } |
- }; |
- |
- private void startScaleDownReturnToStartAnimation(int from, |
- Animation.AnimationListener listener) { |
- mFrom = from; |
- if (isAlphaUsedForScale()) { |
- mStartingScale = mProgress.getAlpha(); |
- } else { |
- mStartingScale = ViewCompat.getScaleX(mCircleView); |
- } |
- 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); |
- } |
- mCircleView.clearAnimation(); |
- mCircleView.startAnimation(mScaleDownToStartAnimation); |
- } |
- |
- private void setTargetOffsetTopAndBottom(int offset, boolean requiresUpdate) { |
- mCircleView.bringToFront(); |
- mCircleView.offsetTopAndBottom(offset); |
- mCurrentTargetOffsetTop = mCircleView.getTop(); |
- if (requiresUpdate && android.os.Build.VERSION.SDK_INT < 11) { |
- invalidate(); |
- } |
- } |
- |
- 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. |
- */ |
- public interface OnRefreshListener { |
- public void onRefresh(); |
- } |
-} |