private void finishSpinner(float overscrollTop) { 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); } }
@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 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); }
@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 initialDownY = getMotionEventY(ev, mActivePointerId); if (initialDownY == -1) { return false; } mInitialDownY = initialDownY; break; 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 - mInitialDownY; if (yDiff > mTouchSlop && !mIsBeingDragged) { mInitialMotionY = mInitialDownY + mTouchSlop; 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; }
@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; // mSpinnerFinalOffset; } targetTop = (mFrom + (int) ((endTarget - mFrom) * interpolatedTime)); int offset = targetTop - mCircleView.getTop(); setTargetOffsetTopAndBottom(offset, false /* requires update */); mProgress.setArrowScale(1 - interpolatedTime); }
/** 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); }
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); }
private void moveSpinner(float overscrollTop) { mProgress.showArrow(true); float originalDragPercent = overscrollTop / mTotalDragDistance; 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 = 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 */); }
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); }
/** * 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 */ @ColorInt public void setColorSchemeColors(int... colors) { ensureTarget(); mProgress.setColorSchemeColors(colors); }
/** * Set the background color of the progress spinner disc. * * @param color */ public void setProgressBackgroundColorSchemeColor(@ColorInt int color) { mCircleView.setBackgroundColor(color); mProgress.setBackgroundColor(color); }
private void startProgressAlphaMaxAnimation() { mAlphaMaxAnimation = startAlphaAnimation(mProgress.getAlpha(), MAX_ALPHA); }
private void startProgressAlphaStartAnimation() { mAlphaStartAnimation = startAlphaAnimation(mProgress.getAlpha(), STARTING_PROGRESS_ALPHA); }
private void setColorViewAlpha(int targetAlpha) { mCircleView.getBackground().setAlpha(targetAlpha); mProgress.setAlpha(targetAlpha); }