Improve ProgressView

This commit is contained in:
seven332 committed 2015-08-06 23:14:43 +08:00
1 parent 76a241d2da
commit b6c726162d
2 files changed
+135 -144

No files matched your search

@@ -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));
}
}
}
@@ -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<Animator> 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));
}
}
}