Improve ProgressView
This commit is contained in:
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user