From b6c726162d24b0b426d3519360d51584485dbe3c Mon Sep 17 00:00:00 2001 From: seven332 Date: Thu, 6 Aug 2015 23:14:43 +0800 Subject: [PATCH] Improve ProgressView --- .../ehviewer/gallery/ui/ProgressView.java | 130 +++++++-------- .../java/com/hippo/widget/ProgressView.java | 149 ++++++++---------- 2 files changed, 135 insertions(+), 144 deletions(-) diff --git a/app/src/main/java/com/hippo/ehviewer/gallery/ui/ProgressView.java b/app/src/main/java/com/hippo/ehviewer/gallery/ui/ProgressView.java index 729569c50..660150ec8 100644 --- a/app/src/main/java/com/hippo/ehviewer/gallery/ui/ProgressView.java +++ b/app/src/main/java/com/hippo/ehviewer/gallery/ui/ProgressView.java @@ -1,13 +1,30 @@ +/* + * Copyright 2015 Hippo Seven + * + * 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 com.hippo.ehviewer.gallery.ui; import android.graphics.Color; -import android.view.animation.AccelerateDecelerateInterpolator; +import android.graphics.Path; import android.view.animation.Interpolator; import android.view.animation.LinearInterpolator; import com.hippo.ehviewer.gallery.anim.Animation; import com.hippo.ehviewer.gallery.glrenderer.GLCanvas; import com.hippo.ehviewer.gallery.glrenderer.GLPaint; +import com.hippo.vectorold.animation.PathInterpolator; import com.hippo.yorozuya.MathUtils; import java.util.ArrayList; @@ -15,11 +32,23 @@ import java.util.List; public class ProgressView extends GLView { + private static final Interpolator TRIM_START_INTERPOLATOR; + private static final Interpolator TRIM_END_INTERPOLATOR; private static final Interpolator LINEAR_INTERPOLATOR = new LinearInterpolator(); - private static final Interpolator END_CURVE_INTERPOLATOR = new EndCurveInterpolator(); - private static final Interpolator START_CURVE_INTERPOLATOR = new StartCurveInterpolator(); - private static final long ANIMATION_DURATION = 1333; + static { + Path trimStartPath = new Path(); + trimStartPath.moveTo(0.0f, 0.0f); + trimStartPath.lineTo(0.5f, 0.0f); + trimStartPath.cubicTo(0.7f, 0.0f, 0.6f, 1f, 1f, 1f); + TRIM_START_INTERPOLATOR = PathInterpolator.build(trimStartPath); + + Path trimEndPath = new Path(); + trimEndPath.moveTo(0.0f, 0.0f); + trimEndPath.cubicTo(0.2f, 0.0f, 0.1f, 1f, 0.5f, 1f); + trimEndPath.lineTo(1f, 1f); + TRIM_END_INTERPOLATOR = PathInterpolator.build(trimEndPath); + } private GLPaint mGLPaint; @@ -28,10 +57,10 @@ public class ProgressView extends GLView { private float mRadiusX; private float mRadiusY; - private float mStartTrim = 0.0f; - private float mEndTrim = 0.0f; + private float mTrimStart = 0.0f; + private float mTrimEnd = 0.0f; + private float mTrimOffset = 0.0f; private float mTrimRotation = 0.0f; - private float mCanvasRotation = 0.0f; private boolean mIndeterminate = false; @@ -47,50 +76,50 @@ public class ProgressView extends GLView { } public void setupAnimations() { - Animation endTrim = new Animation() { + Animation trimStart = new Animation() { @Override protected void onCalculate(float progress) { - mEndTrim = MathUtils.lerp(0.0f, 0.75f, progress); + mTrimStart = MathUtils.lerp(0.0f, 0.75f, progress); } }; - endTrim.setDuration(ANIMATION_DURATION); - endTrim.setInterpolator(START_CURVE_INTERPOLATOR); - endTrim.setRepeatCount(Animation.INFINITE); + trimStart.setDuration(1333L); + trimStart.setInterpolator(TRIM_START_INTERPOLATOR); + trimStart.setRepeatCount(Animation.INFINITE); - Animation startTrim = new Animation() { + Animation trimEnd = new Animation() { @Override protected void onCalculate(float progress) { - mStartTrim = MathUtils.lerp(0.0f, 0.75f, progress); + mTrimEnd = MathUtils.lerp(0.0f, 0.75f, progress); } }; - startTrim.setDuration(ANIMATION_DURATION); - startTrim.setInterpolator(END_CURVE_INTERPOLATOR); - startTrim.setRepeatCount(Animation.INFINITE); + trimEnd.setDuration(1333L); + trimEnd.setInterpolator(TRIM_END_INTERPOLATOR); + trimEnd.setRepeatCount(Animation.INFINITE); + + Animation trimOffset = new Animation() { + @Override + protected void onCalculate(float progress) { + mTrimOffset = MathUtils.lerp(0.0f, 0.25f, progress); + } + }; + trimOffset.setDuration(1333L); + trimOffset.setInterpolator(LINEAR_INTERPOLATOR); + trimOffset.setRepeatCount(Animation.INFINITE); Animation trimRotation = new Animation() { @Override protected void onCalculate(float progress) { - mTrimRotation = MathUtils.lerp(0.0f, 0.25f, progress); + mTrimRotation = MathUtils.lerp(0.0f, 720.0f, progress); } }; - trimRotation.setDuration(ANIMATION_DURATION); + trimRotation.setDuration(6665L); trimRotation.setInterpolator(LINEAR_INTERPOLATOR); trimRotation.setRepeatCount(Animation.INFINITE); - Animation canvasRotation = new Animation() { - @Override - protected void onCalculate(float progress) { - mCanvasRotation = MathUtils.lerp(0.0f, 720.0f, progress); - } - }; - canvasRotation.setDuration(6665L); - canvasRotation.setInterpolator(LINEAR_INTERPOLATOR); - canvasRotation.setRepeatCount(Animation.INFINITE); - - mAnimations.add(endTrim); - mAnimations.add(startTrim); + mAnimations.add(trimStart); + mAnimations.add(trimEnd); + mAnimations.add(trimOffset); mAnimations.add(trimRotation); - mAnimations.add(canvasRotation); } private void startAnimations() { @@ -144,10 +173,10 @@ public class ProgressView extends GLView { public void setProgress(float progress) { if (!mIndeterminate) { - mStartTrim = 0; - mEndTrim = progress; + mTrimStart = 0.0f; + mTrimEnd = progress; + mTrimOffset = 0.0f; mTrimRotation = 0.0f; - mCanvasRotation = -90f; invalidate(); } } @@ -161,21 +190,12 @@ public class ProgressView extends GLView { int cx = width / 2; int cy = height / 2; - float startAngle = (mStartTrim + mTrimRotation) * 360.0f; - float endAngle = (mEndTrim + mTrimRotation) * 360.0f; - float sweepAngle = endAngle - startAngle; - if (mIndeterminate) { - float diameter = Math.min(mRadiusX, mRadiusY) * 2; - float minAngle = Math.max((float) (360.0D / (diameter * 3.141592653589793D)), 3f); - if ((sweepAngle < minAngle) && (sweepAngle > -minAngle)) { - float symbol = Math.signum(sweepAngle); - sweepAngle = (Math.abs(symbol) == 1f ? symbol : 1f) * minAngle; - } - } + float startAngle = (mTrimStart + mTrimOffset) * 360.0f - 90; + float sweepAngle = (mTrimEnd - mTrimStart) * 360.0f; + float rotation = mTrimRotation + startAngle; canvas.save(); - float rotation = MathUtils.positiveModulo(mCanvasRotation + startAngle, 360); canvas.translate(cx, cy); canvas.rotate(rotation, 0, 0, 1); if (rotation % 180 != 0) { @@ -204,20 +224,4 @@ public class ProgressView extends GLView { invalidate(); } } - - private static class EndCurveInterpolator extends AccelerateDecelerateInterpolator { - - @Override - public float getInterpolation(float input) { - return super.getInterpolation(Math.max(0.0f, (input - 0.5f) * 2.0f)); - } - } - - private static class StartCurveInterpolator extends AccelerateDecelerateInterpolator { - - @Override - public float getInterpolation(float input) { - return super.getInterpolation(Math.min(1.0f, input * 2.0f)); - } - } } diff --git a/app/src/main/java/com/hippo/widget/ProgressView.java b/app/src/main/java/com/hippo/widget/ProgressView.java index d30d1c52a..10d14e64c 100644 --- a/app/src/main/java/com/hippo/widget/ProgressView.java +++ b/app/src/main/java/com/hippo/widget/ProgressView.java @@ -23,17 +23,19 @@ import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; +import android.graphics.Path; import android.graphics.RectF; import android.os.Build; import android.support.annotation.NonNull; import android.support.v4.view.ViewCompat; import android.util.AttributeSet; import android.view.View; -import android.view.animation.AccelerateDecelerateInterpolator; +import android.view.animation.Animation; import android.view.animation.Interpolator; import android.view.animation.LinearInterpolator; import com.hippo.ehviewer.R; +import com.hippo.vectorold.animation.PathInterpolator; import com.hippo.yorozuya.ViewUtils; import java.util.ArrayList; @@ -41,11 +43,23 @@ import java.util.ArrayList; // Base on android.graphics.drawable.MaterialProgressDrawable in L preview public class ProgressView extends View { + private static final Interpolator TRIM_START_INTERPOLATOR; + private static final Interpolator TRIM_END_INTERPOLATOR; private static final Interpolator LINEAR_INTERPOLATOR = new LinearInterpolator(); - private static final Interpolator END_CURVE_INTERPOLATOR = new EndCurveInterpolator(); - private static final Interpolator START_CURVE_INTERPOLATOR = new StartCurveInterpolator(); - private static final long ANIMATION_DURATION = 1333; + static { + Path trimStartPath = new Path(); + trimStartPath.moveTo(0.0f, 0.0f); + trimStartPath.lineTo(0.5f, 0.0f); + trimStartPath.cubicTo(0.7f, 0.0f, 0.6f, 1f, 1f, 1f); + TRIM_START_INTERPOLATOR = PathInterpolator.build(trimStartPath); + + Path trimEndPath = new Path(); + trimEndPath.moveTo(0.0f, 0.0f); + trimEndPath.cubicTo(0.2f, 0.0f, 0.1f, 1f, 0.5f, 1f); + trimEndPath.lineTo(1f, 1f); + TRIM_END_INTERPOLATOR = PathInterpolator.build(trimEndPath); + } private final ArrayList mAnimators = new ArrayList<>(); private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); @@ -53,10 +67,10 @@ public class ProgressView extends View { private boolean mIndeterminate; - private float mStartTrim = 0.0f; - private float mEndTrim = 0.0f; + private float mTrimStart = 0.0f; + private float mTrimEnd = 0.0f; + private float mTrimOffset = 0.0f; private float mTrimRotation = 0.0f; - private float mCanvasRotation = 0.0f; // It is a trick to avoid first sight stuck. Get it from ProgressBar private boolean mShouldStartAnimationDrawable = false; @@ -86,34 +100,30 @@ public class ProgressView extends View { } private void setupAnimators() { - ObjectAnimator endTrim = ObjectAnimator.ofFloat(this, "endTrim", 0.0f, 0.75f); - endTrim.setDuration(ANIMATION_DURATION); - endTrim.setInterpolator(START_CURVE_INTERPOLATOR); - endTrim.setRepeatCount(-1); - endTrim.setRepeatMode(1); + ObjectAnimator trimStart = ObjectAnimator.ofFloat(this, "trimStart", 0.0f, 0.75f); + trimStart.setDuration(1333L); + trimStart.setInterpolator(TRIM_START_INTERPOLATOR); + trimStart.setRepeatCount(Animation.INFINITE); - ObjectAnimator startTrim = ObjectAnimator.ofFloat(this, "startTrim", 0.0f, 0.75f); - startTrim.setDuration(ANIMATION_DURATION); - startTrim.setInterpolator(END_CURVE_INTERPOLATOR); - startTrim.setRepeatCount(-1); - startTrim.setRepeatMode(1); + ObjectAnimator trimEnd = ObjectAnimator.ofFloat(this, "trimEnd", 0.0f, 0.75f); + trimEnd.setDuration(1333L); + trimEnd.setInterpolator(TRIM_END_INTERPOLATOR); + trimEnd.setRepeatCount(Animation.INFINITE); - ObjectAnimator trimRotation = ObjectAnimator.ofFloat(this, "trimRotation", 0.0f, 0.25f); - trimRotation.setDuration(ANIMATION_DURATION); + ObjectAnimator trimOffset = ObjectAnimator.ofFloat(this, "trimOffset", 0.0f, 0.25f); + trimOffset.setDuration(1333L); + trimOffset.setInterpolator(LINEAR_INTERPOLATOR); + trimOffset.setRepeatCount(Animation.INFINITE); + + ObjectAnimator trimRotation = ObjectAnimator.ofFloat(this, "trimRotation", 0.0f, 720.0f); + trimRotation.setDuration(6665L); trimRotation.setInterpolator(LINEAR_INTERPOLATOR); - trimRotation.setRepeatCount(-1); - trimRotation.setRepeatMode(1); + trimRotation.setRepeatCount(Animation.INFINITE); - ObjectAnimator canvasRotation = ObjectAnimator.ofFloat(this, "canvasRotation", 0.0f, 720.0f); - canvasRotation.setDuration(6665L); - canvasRotation.setInterpolator(LINEAR_INTERPOLATOR); - canvasRotation.setRepeatCount(-1); - canvasRotation.setRepeatMode(1); - - mAnimators.add(endTrim); - mAnimators.add(startTrim); + mAnimators.add(trimStart); + mAnimators.add(trimEnd); + mAnimators.add(trimOffset); mAnimators.add(trimRotation); - mAnimators.add(canvasRotation); } private void startAnimation() { @@ -171,24 +181,35 @@ public class ProgressView extends View { } @SuppressWarnings("unused") - public float getStartTrim() { - return mStartTrim; + public float getTrimStart() { + return mTrimStart; } @SuppressWarnings("unused") - public void setStartTrim(float startTrim) { - mStartTrim = startTrim; + public void setTrimStart(float trimStart) { + mTrimStart = trimStart; invalidate(); } @SuppressWarnings("unused") - public float getEndTrim() { - return mEndTrim; + public float getTrimEnd() { + return mTrimEnd; } @SuppressWarnings("unused") - public void setEndTrim(float endTrim) { - mEndTrim = endTrim; + public void setTrimEnd(float trimEnd) { + mTrimEnd = trimEnd; + invalidate(); + } + + @SuppressWarnings("unused") + public float getTrimOffset() { + return mTrimOffset; + } + + @SuppressWarnings("unused") + public void setTrimOffset(float trimOffset) { + mTrimOffset = trimOffset; invalidate(); } @@ -203,17 +224,6 @@ public class ProgressView extends View { invalidate(); } - @SuppressWarnings("unused") - public float getCanvasRotation() { - return mCanvasRotation; - } - - @SuppressWarnings("unused") - public void setCanvasRotation(float canvasRotation) { - mCanvasRotation = canvasRotation; - invalidate(); - } - @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); @@ -285,17 +295,18 @@ public class ProgressView extends View { public void setProgress(float progress) { if (!mIndeterminate) { - mStartTrim = -0.25f; - mEndTrim = progress - 0.25f; - mTrimRotation = 0.0f; - mCanvasRotation = 0.0f; + mTrimStart = 0f; + mTrimEnd = progress; + mTrimOffset = -0.25f; + mTrimRotation = 0f; invalidate(); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - setMeasuredDimension(ViewUtils.getSuitableSize(getSuggestedMinimumWidth(), widthMeasureSpec), ViewUtils.getSuitableSize(getSuggestedMinimumHeight(), heightMeasureSpec)); + setMeasuredDimension(ViewUtils.getSuitableSize(getSuggestedMinimumWidth(), widthMeasureSpec), + ViewUtils.getSuitableSize(getSuggestedMinimumHeight(), heightMeasureSpec)); } @Override @@ -308,18 +319,10 @@ public class ProgressView extends View { @Override protected void onDraw(Canvas canvas) { int saved = canvas.save(); - canvas.rotate(mCanvasRotation, mRectF.centerX(), mRectF.centerY()); + canvas.rotate(mTrimRotation, mRectF.centerX(), mRectF.centerY()); - float startAngle = (mStartTrim + mTrimRotation) * 360.0f; - float endAngle = (mEndTrim + mTrimRotation) * 360.0f; - float sweepAngle = endAngle - startAngle; - if (mIndeterminate) { - float diameter = Math.min(mRectF.width(), mRectF.height()); - float minAngle = (float) (360.0D / (diameter * 3.141592653589793D)); - if ((sweepAngle < minAngle) && (sweepAngle > -minAngle)) { - sweepAngle = Math.signum(sweepAngle) * minAngle; - } - } + float startAngle = (mTrimStart + mTrimOffset) * 360.0f - 90; + float sweepAngle = (mTrimEnd - mTrimStart) * 360.0f; canvas.drawArc(mRectF, startAngle, sweepAngle, false, mPaint); canvas.restoreToCount(saved); @@ -329,20 +332,4 @@ public class ProgressView extends View { startAnimationActually(); } } - - private static class EndCurveInterpolator extends AccelerateDecelerateInterpolator { - - @Override - public float getInterpolation(float input) { - return super.getInterpolation(Math.max(0.0f, (input - 0.5f) * 2.0f)); - } - } - - private static class StartCurveInterpolator extends AccelerateDecelerateInterpolator { - - @Override - public float getInterpolation(float input) { - return super.getInterpolation(Math.min(1.0f, input * 2.0f)); - } - } }