@Override public void transformPage(View view, float position) { int pageWidth = view.getWidth(); if (position < -1) { // [-Infinity,-1) // This page is way off-screen to the left. ViewCompat.setAlpha(view, 0); } else if (position <= 0) { // [-1,0] // Use the default slide transition when moving to the left page ViewCompat.setAlpha(view, 1); ViewCompat.setTranslationX(view, 0); ViewCompat.setScaleX(view, 1); ViewCompat.setScaleY(view, 1); } else if (position <= 1) { // (0,1] // Fade the page out. ViewCompat.setAlpha(view, 1 - position); // Counteract the default slide transition ViewCompat.setTranslationX(view, pageWidth * -position); // Scale the page down (between MIN_SCALE and 1) float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position)); ViewCompat.setScaleX(view, scaleFactor); ViewCompat.setScaleY(view, scaleFactor); } else { // (1,+Infinity] // This page is way off-screen to the right. ViewCompat.setAlpha(view, 0); } }
@Override protected void onRemoveCanceled(ViewHolder holder) { ViewCompat.setRotationY(holder.itemView, 0); ViewCompat.setTranslationX(holder.itemView, 0); ViewCompat.setScaleX(holder.itemView, 1); ViewCompat.setScaleY(holder.itemView, 1); }
private void setAnimationProgress(float progress) { if (isAlphaUsedForScale()) { setColorViewAlpha((int) (progress * 255.0F)); } else { ViewCompat.setScaleX(this.mCircleView, progress); ViewCompat.setScaleY(this.mCircleView, progress); } }
@Override protected void preAnimateAddImpl(RecyclerView.ViewHolder holder) { // @TODO https://code.google.com/p/android/issues/detail?id=80863 // ViewCompat.setPivotY(holder.itemView, holder.itemView.getHeight()); holder.itemView.setPivotY(holder.itemView.getHeight()); ViewCompat.setScaleX(holder.itemView, 0); ViewCompat.setScaleY(holder.itemView, 0); }
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 */); }
public boolean onTouchEvent(MotionEvent ev) { int action = MotionEventCompat.getActionMasked(ev); if ((this.mReturningToStart) && (action == 0)) { this.mReturningToStart = false; } if ((!isEnabled()) || (this.mReturningToStart) || (canChildScrollUp())) { return false; } switch (action) { case 0: this.mActivePointerId = MotionEventCompat.getPointerId(ev, 0); this.mIsBeingDragged = false; break; case 2: int pointerIndex = MotionEventCompat.findPointerIndex(ev, this.mActivePointerId); if (pointerIndex < 0) { Log.e(LOG_TAG, "Got ACTION_MOVE event but have an invalid active pointer id."); return false; } float y = MotionEventCompat.getY(ev, pointerIndex); float overscrollTop = (y - this.mInitialMotionY) * 0.5F; if (this.mIsBeingDragged) { this.mProgress.showArrow(true); float originalDragPercent = overscrollTop / this.mTotalDragDistance; if (originalDragPercent < 0.0F) { return false; } float dragPercent = Math.min(1.0F, Math.abs(originalDragPercent)); float adjustedPercent = (float) Math.max(dragPercent - 0.4D, 0.0D) * 5.0F / 3.0F; float extraOS = Math.abs(overscrollTop) - this.mTotalDragDistance; float slingshotDist = this.mUsingCustomStart ? this.mSpinnerFinalOffset - this.mOriginalOffsetTop : this.mSpinnerFinalOffset; float tensionSlingshotPercent = Math.max(0.0F, Math.min(extraOS, slingshotDist * 2.0F) / slingshotDist); float tensionPercent = (float) (tensionSlingshotPercent / 4.0F - Math.pow(tensionSlingshotPercent / 4.0F, 2.0D)) * 2.0F; float extraMove = slingshotDist * tensionPercent * 2.0F; int targetY = this.mOriginalOffsetTop + (int) (slingshotDist * dragPercent + extraMove); if (this.mCircleView.getVisibility() != 0) { this.mCircleView.setVisibility(0); } if (!this.mScale) { ViewCompat.setScaleX(this.mCircleView, 1.0F); ViewCompat.setScaleY(this.mCircleView, 1.0F); } if (overscrollTop < this.mTotalDragDistance) { if (this.mScale) { setAnimationProgress(overscrollTop / this.mTotalDragDistance); } if ((this.mProgress.getAlpha() > 76) && (!isAnimationRunning(this.mAlphaStartAnimation))) { startProgressAlphaStartAnimation(); } float strokeStart = adjustedPercent * 0.8F; this.mProgress.setStartEndTrim(0.0F, Math.min(0.8F, strokeStart)); this.mProgress.setArrowScale(Math.min(1.0F, adjustedPercent)); } else if ((this.mProgress.getAlpha() < 255) && (!isAnimationRunning(this.mAlphaMaxAnimation))) { startProgressAlphaMaxAnimation(); } float rotation = (-0.25F + 0.4F * adjustedPercent + tensionPercent * 2.0F) * 0.5F; this.mProgress.setProgressRotation(rotation); setTargetOffsetTopAndBottom(targetY - this.mCurrentTargetOffsetTop, true); } break; case 5: int index = MotionEventCompat.getActionIndex(ev); this.mActivePointerId = MotionEventCompat.getPointerId(ev, index); break; case 6: onSecondaryPointerUp(ev); break; case 1: case 3: if (this.mActivePointerId == -1) { if (action == 1) { Log.e(LOG_TAG, "Got ACTION_UP event but don't have an active pointer id."); } return false; } int pointerIndex_1 = MotionEventCompat.findPointerIndex(ev, this.mActivePointerId); float y_1 = MotionEventCompat.getY(ev, pointerIndex_1); float overscrollTop_1 = (y_1 - this.mInitialMotionY) * 0.5F; this.mIsBeingDragged = false; if (overscrollTop_1 > this.mTotalDragDistance) { setRefreshing(true, true); } else { this.mRefreshing = false; this.mProgress.setStartEndTrim(0.0F, 0.0F); Animation.AnimationListener listener = null; if (!this.mScale) listener = new Animation.AnimationListener() { public void onAnimationStart(Animation animation) {} public void onAnimationEnd(Animation animation) { if (!MySwipeRefreshLayout.this.mScale) MySwipeRefreshLayout.this.startScaleDownAnimation(null); } public void onAnimationRepeat(Animation animation) {} }; animateOffsetToStartPosition(this.mCurrentTargetOffsetTop, listener); this.mProgress.showArrow(false); } this.mActivePointerId = -1; return false; case 4: } return true; }
protected void preAnimateAdd(RecyclerView.ViewHolder holder) { super.preAnimateAdd(holder); ViewCompat.setAlpha(holder.itemView, 0); ViewCompat.setScaleX(holder.itemView, 1.5f); ViewCompat.setScaleY(holder.itemView, 1.5f); }
@Override protected void preAnimateAddImpl(RecyclerView.ViewHolder holder) { ViewCompat.setScaleX(holder.itemView, 0); ViewCompat.setScaleY(holder.itemView, 0); }
public void handleScale(float scale) { scale = 0.1f + 0.9f * scale; ViewCompat.setScaleX(mPullDownView, scale); ViewCompat.setPivotY(mPullDownView, mPullDownView.getHeight()); ViewCompat.setScaleY(mPullDownView, scale); }
@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 = 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; }