mirror of https://github.com/NekoX-Dev/NekoX.git
919 lines
38 KiB
Java
919 lines
38 KiB
Java
package org.telegram.ui.Components;
|
|
|
|
import android.graphics.Canvas;
|
|
import android.graphics.ColorFilter;
|
|
import android.graphics.LinearGradient;
|
|
import android.graphics.Matrix;
|
|
import android.graphics.Paint;
|
|
import android.graphics.Path;
|
|
import android.graphics.PixelFormat;
|
|
import android.graphics.PorterDuff;
|
|
import android.graphics.PorterDuffColorFilter;
|
|
import android.graphics.RectF;
|
|
import android.graphics.Shader;
|
|
import android.graphics.drawable.Drawable;
|
|
import android.text.TextPaint;
|
|
import android.util.Log;
|
|
import android.view.animation.DecelerateInterpolator;
|
|
|
|
import org.telegram.messenger.AndroidUtilities;
|
|
import org.telegram.ui.ActionBar.Theme;
|
|
|
|
public class MediaActionDrawable extends Drawable {
|
|
|
|
public static final int ICON_PLAY = 0;
|
|
public static final int ICON_PAUSE = 1;
|
|
public static final int ICON_DOWNLOAD = 2;
|
|
public static final int ICON_CANCEL = 3;
|
|
public static final int ICON_NONE = 4;
|
|
public static final int ICON_FILE = 5;
|
|
public static final int ICON_CHECK = 6;
|
|
public static final int ICON_FIRE = 7;
|
|
public static final int ICON_GIF = 8;
|
|
public static final int ICON_SECRETCHECK = 9;
|
|
public static final int ICON_EMPTY = 10;
|
|
public static final int ICON_EMPTY_NOPROGRESS = 11;
|
|
public static final int ICON_CANCEL_NOPROFRESS = 12;
|
|
public static final int ICON_CANCEL_PERCENT = 13;
|
|
public static final int ICON_CANCEL_FILL = 14;
|
|
public static final int ICON_UPDATE = 15;
|
|
|
|
private TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
|
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
private Paint backPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
private Paint paint2 = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
private Paint paint3 = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
private RectF rect = new RectF();
|
|
private ColorFilter colorFilter;
|
|
private float scale = 1.0f;
|
|
private DecelerateInterpolator interpolator = new DecelerateInterpolator();
|
|
|
|
private boolean isMini;
|
|
|
|
private float transitionAnimationTime = 400.0f;
|
|
|
|
private int lastPercent = -1;
|
|
private String percentString;
|
|
private int percentStringWidth;
|
|
|
|
private float overrideAlpha = 1.0f;
|
|
|
|
private int currentIcon;
|
|
private int nextIcon;
|
|
private float transitionProgress = 1.0f;
|
|
private float savedTransitionProgress;
|
|
private long lastAnimationTime;
|
|
private boolean animatingTransition;
|
|
|
|
private float downloadRadOffset;
|
|
private float downloadProgress;
|
|
private float animatedDownloadProgress;
|
|
private float downloadProgressAnimationStart;
|
|
private float downloadProgressTime;
|
|
|
|
private final static float EPS = 0.001f;
|
|
|
|
private final static float DOWNLOAD_TO_CANCEL_STAGE1 = 0.5f;
|
|
private final static float DOWNLOAD_TO_CANCEL_STAGE2 = 0.2f;
|
|
private final static float DOWNLOAD_TO_CANCEL_STAGE3 = 0.3f;
|
|
|
|
private final static float CANCEL_TO_CHECK_STAGE1 = 0.5f;
|
|
private final static float CANCEL_TO_CHECK_STAGE2 = 0.5f;
|
|
|
|
private MediaActionDrawableDelegate delegate;
|
|
|
|
private Theme.MessageDrawable messageDrawable;
|
|
private LinearGradient gradientDrawable;
|
|
private Matrix gradientMatrix;
|
|
private boolean hasOverlayImage;
|
|
|
|
public interface MediaActionDrawableDelegate {
|
|
void invalidate();
|
|
}
|
|
|
|
public MediaActionDrawable() {
|
|
paint.setColor(0xffffffff);
|
|
paint.setStrokeCap(Paint.Cap.ROUND);
|
|
paint.setStrokeWidth(AndroidUtilities.dp(3));
|
|
paint.setStyle(Paint.Style.STROKE);
|
|
|
|
paint3.setColor(0xffffffff);
|
|
|
|
textPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
|
textPaint.setTextSize(AndroidUtilities.dp(13));
|
|
textPaint.setColor(0xffffffff);
|
|
|
|
paint2.setColor(0xffffffff);
|
|
}
|
|
|
|
@Override
|
|
public void setAlpha(int alpha) {
|
|
|
|
}
|
|
|
|
public void setOverrideAlpha(float alpha) {
|
|
overrideAlpha = alpha;
|
|
}
|
|
|
|
@Override
|
|
public void setColorFilter(ColorFilter colorFilter) {
|
|
paint.setColorFilter(colorFilter);
|
|
paint2.setColorFilter(colorFilter);
|
|
paint3.setColorFilter(colorFilter);
|
|
textPaint.setColorFilter(colorFilter);
|
|
}
|
|
|
|
public void setColor(int value) {
|
|
paint.setColor(value | 0xff000000);
|
|
paint2.setColor(value | 0xff000000);
|
|
paint3.setColor(value | 0xff000000);
|
|
textPaint.setColor(value | 0xff000000);
|
|
colorFilter = new PorterDuffColorFilter(value, PorterDuff.Mode.MULTIPLY);
|
|
}
|
|
|
|
public void setBackColor(int value) {
|
|
backPaint.setColor(value | 0xff000000);
|
|
}
|
|
|
|
public int getColor() {
|
|
return paint.getColor();
|
|
}
|
|
|
|
public void setMini(boolean value) {
|
|
isMini = value;
|
|
paint.setStrokeWidth(AndroidUtilities.dp(isMini ? 2 : 3));
|
|
}
|
|
|
|
@Override
|
|
public int getOpacity() {
|
|
return PixelFormat.TRANSPARENT;
|
|
}
|
|
|
|
public void setDelegate(MediaActionDrawableDelegate mediaActionDrawableDelegate) {
|
|
delegate = mediaActionDrawableDelegate;
|
|
}
|
|
|
|
public boolean setIcon(int icon, boolean animated) {
|
|
if (currentIcon == icon && nextIcon != icon) {
|
|
currentIcon = nextIcon;
|
|
transitionProgress = 1.0f;
|
|
}
|
|
if (animated) {
|
|
if (currentIcon == icon || nextIcon == icon) {
|
|
return false;
|
|
}
|
|
if (currentIcon == ICON_PLAY && icon == ICON_PAUSE || currentIcon == ICON_PAUSE && icon == ICON_PLAY) {
|
|
transitionAnimationTime = 300.0f;
|
|
} else if (currentIcon == ICON_DOWNLOAD && (icon == ICON_CANCEL || icon == ICON_CANCEL_FILL)) {
|
|
transitionAnimationTime = 400.0f;
|
|
} else if (currentIcon != ICON_NONE && icon == ICON_CHECK) {
|
|
transitionAnimationTime = 360.0f;
|
|
} else if (currentIcon == ICON_NONE && icon == ICON_CANCEL_FILL || currentIcon == ICON_CANCEL_FILL && icon == ICON_NONE) {
|
|
transitionAnimationTime = 160.0f;
|
|
} else {
|
|
transitionAnimationTime = 220.0f;
|
|
}
|
|
if (animatingTransition) {
|
|
currentIcon = nextIcon;
|
|
}
|
|
animatingTransition = true;
|
|
nextIcon = icon;
|
|
savedTransitionProgress = transitionProgress;
|
|
transitionProgress = 0.0f;
|
|
} else {
|
|
if (currentIcon == icon) {
|
|
return false;
|
|
}
|
|
animatingTransition = false;
|
|
currentIcon = nextIcon = icon;
|
|
savedTransitionProgress = transitionProgress;
|
|
transitionProgress = 1.0f;
|
|
}
|
|
if (icon == ICON_CANCEL || icon == ICON_CANCEL_FILL) {
|
|
downloadRadOffset = 112;
|
|
animatedDownloadProgress = 0.0f;
|
|
downloadProgressAnimationStart = 0.0f;
|
|
downloadProgressTime = 0.0f;
|
|
}
|
|
invalidateSelf();
|
|
return true;
|
|
}
|
|
|
|
public int getCurrentIcon() {
|
|
return nextIcon;
|
|
}
|
|
|
|
public int getPreviousIcon() {
|
|
return currentIcon;
|
|
}
|
|
|
|
public void setProgress(float value, boolean animated) {
|
|
if (!animated) {
|
|
animatedDownloadProgress = value;
|
|
downloadProgressAnimationStart = value;
|
|
} else {
|
|
if (animatedDownloadProgress > value) {
|
|
animatedDownloadProgress = value;
|
|
}
|
|
downloadProgressAnimationStart = animatedDownloadProgress;
|
|
}
|
|
downloadProgress = value;
|
|
downloadProgressTime = 0;
|
|
invalidateSelf();
|
|
}
|
|
|
|
public float getProgress() {
|
|
return downloadProgress;
|
|
}
|
|
|
|
public static float getCircleValue(float value) {
|
|
while (value > 360) {
|
|
value -= 360;
|
|
}
|
|
return value;
|
|
}
|
|
|
|
public float getProgressAlpha() {
|
|
return 1.0f - transitionProgress;
|
|
}
|
|
|
|
public float getTransitionProgress() {
|
|
return animatingTransition ? transitionProgress : 1.0f;
|
|
}
|
|
|
|
public void setBackgroundDrawable(Theme.MessageDrawable drawable) {
|
|
messageDrawable = drawable;
|
|
}
|
|
|
|
public void setBackgroundGradientDrawable(LinearGradient drawable) {
|
|
gradientDrawable = drawable;
|
|
gradientMatrix = new Matrix();
|
|
}
|
|
|
|
public void setHasOverlayImage(boolean value) {
|
|
hasOverlayImage = value;
|
|
}
|
|
|
|
@Override
|
|
public void setBounds(int left, int top, int right, int bottom) {
|
|
super.setBounds(left, top, right, bottom);
|
|
scale = (right - left) / (float) getIntrinsicWidth();
|
|
if (scale < 0.7f) {
|
|
paint.setStrokeWidth(AndroidUtilities.dp(2));
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void invalidateSelf() {
|
|
super.invalidateSelf();
|
|
if (delegate != null) {
|
|
delegate.invalidate();
|
|
}
|
|
}
|
|
|
|
private void applyShaderMatrix(boolean path) {
|
|
if (messageDrawable != null && messageDrawable.hasGradient() && !hasOverlayImage) {
|
|
android.graphics.Rect bounds = getBounds();
|
|
Shader shader = messageDrawable.getGradientShader();
|
|
Matrix matrix = messageDrawable.getMatrix();
|
|
matrix.reset();
|
|
messageDrawable.applyMatrixScale();
|
|
if (path) {
|
|
matrix.postTranslate(-bounds.centerX(), -messageDrawable.getTopY() + bounds.top);
|
|
} else {
|
|
matrix.postTranslate(0, -messageDrawable.getTopY());
|
|
}
|
|
shader.setLocalMatrix(matrix);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void draw(Canvas canvas) {
|
|
android.graphics.Rect bounds = getBounds();
|
|
|
|
if (messageDrawable != null && messageDrawable.hasGradient() && !hasOverlayImage) {
|
|
Shader shader = messageDrawable.getGradientShader();
|
|
paint.setShader(shader);
|
|
paint2.setShader(shader);
|
|
paint3.setShader(shader);
|
|
} else if (gradientDrawable != null && !hasOverlayImage) {
|
|
gradientMatrix.reset();
|
|
gradientMatrix.setTranslate(0, bounds.top);
|
|
gradientDrawable.setLocalMatrix(gradientMatrix);
|
|
paint.setShader(gradientDrawable);
|
|
paint2.setShader(gradientDrawable);
|
|
paint3.setShader(gradientDrawable);
|
|
} else {
|
|
paint.setShader(null);
|
|
paint2.setShader(null);
|
|
paint3.setShader(null);
|
|
}
|
|
|
|
int cx = bounds.centerX();
|
|
int cy = bounds.centerY();
|
|
|
|
int saveCount = 0;
|
|
|
|
if (nextIcon == ICON_NONE) {
|
|
if (currentIcon != ICON_CANCEL && currentIcon != ICON_CANCEL_FILL) {
|
|
saveCount = canvas.save();
|
|
float progress = 1.0f - transitionProgress;
|
|
canvas.scale(progress, progress, cx, cy);
|
|
}
|
|
} else if ((nextIcon == ICON_CHECK || nextIcon == ICON_EMPTY) && currentIcon == ICON_NONE) {
|
|
saveCount = canvas.save();
|
|
canvas.scale(transitionProgress, transitionProgress, cx, cy);
|
|
}
|
|
|
|
int width = AndroidUtilities.dp(3);
|
|
if (currentIcon == ICON_DOWNLOAD || nextIcon == ICON_DOWNLOAD) {
|
|
applyShaderMatrix(false);
|
|
float yStart = cy - AndroidUtilities.dp(9) * scale;
|
|
float yEnd = cy + AndroidUtilities.dp(9) * scale;
|
|
float yStart2;
|
|
float yEnd2 = cy + AndroidUtilities.dp(12) * scale;
|
|
|
|
float transition;
|
|
if ((currentIcon == ICON_CANCEL || currentIcon == ICON_CANCEL_FILL) && nextIcon == ICON_DOWNLOAD) {
|
|
paint.setAlpha((int) (255 * Math.min(1.0f, transitionProgress / 0.5f)));
|
|
transition = transitionProgress;
|
|
yStart2 = cy + AndroidUtilities.dp(12) * scale;
|
|
} else {
|
|
if (nextIcon != ICON_CANCEL && nextIcon != ICON_CANCEL_FILL && nextIcon != ICON_DOWNLOAD) {
|
|
paint.setAlpha((int) (255 * Math.min(1.0f, savedTransitionProgress / 0.5f) * (1.0f - transitionProgress)));
|
|
transition = savedTransitionProgress;
|
|
} else {
|
|
paint.setAlpha(255);
|
|
transition = transitionProgress;
|
|
}
|
|
yStart2 = cy + AndroidUtilities.dp(1) * scale;
|
|
}
|
|
|
|
float y1, y2, x1, x2, y3;
|
|
if (animatingTransition) {
|
|
float progress = transition;
|
|
if (nextIcon == ICON_DOWNLOAD || progress <= DOWNLOAD_TO_CANCEL_STAGE1) {
|
|
float currentProgress;
|
|
float currentBackProgress;
|
|
if (nextIcon == ICON_DOWNLOAD) {
|
|
currentBackProgress = transition;
|
|
currentProgress = 1.0f - currentBackProgress;
|
|
} else {
|
|
currentProgress = transition / DOWNLOAD_TO_CANCEL_STAGE1;
|
|
currentBackProgress = 1.0f - currentProgress;
|
|
}
|
|
y1 = yStart + (yStart2 - yStart) * currentProgress;
|
|
y2 = yEnd + (yEnd2 - yEnd) * currentProgress;
|
|
x1 = cx - AndroidUtilities.dp(8) * currentBackProgress * scale;
|
|
x2 = cx + AndroidUtilities.dp(8) * currentBackProgress * scale;
|
|
y3 = y2 - AndroidUtilities.dp(8) * currentBackProgress * scale;
|
|
} else {
|
|
float currentProgress;
|
|
float currentProgress2;
|
|
float currentProgress3;
|
|
float d = AndroidUtilities.dp(13) * scale * scale + (isMini ? AndroidUtilities.dp(2) : 0);
|
|
|
|
progress -= DOWNLOAD_TO_CANCEL_STAGE1;
|
|
currentProgress3 = progress / (DOWNLOAD_TO_CANCEL_STAGE2 + DOWNLOAD_TO_CANCEL_STAGE3);
|
|
if (progress > DOWNLOAD_TO_CANCEL_STAGE2) {
|
|
progress -= DOWNLOAD_TO_CANCEL_STAGE2;
|
|
currentProgress = 1.0f;
|
|
currentProgress2 = progress / DOWNLOAD_TO_CANCEL_STAGE3;
|
|
} else {
|
|
currentProgress = progress / DOWNLOAD_TO_CANCEL_STAGE2;
|
|
currentProgress2 = 0.0f;
|
|
}
|
|
rect.set(cx - d, yEnd2 - d / 2, cx, yEnd2 + d / 2);
|
|
float start = 100 * currentProgress2;
|
|
canvas.drawArc(rect, start, 104 * currentProgress3 - start, false, paint);
|
|
|
|
y1 = yStart2 + (yEnd2 - yStart2) * currentProgress;
|
|
y2 = y3 = yEnd2;
|
|
x1 = x2 = cx;
|
|
|
|
if (currentProgress2 > 0) {
|
|
float rotation;
|
|
if (nextIcon == ICON_CANCEL_FILL) {
|
|
rotation = 0;
|
|
} else {
|
|
rotation = -45 * (1.0f - currentProgress2);
|
|
}
|
|
d = AndroidUtilities.dp(7) * currentProgress2 * scale;
|
|
int alpha = (int) (255 * currentProgress2);
|
|
if (nextIcon != ICON_CANCEL && nextIcon != ICON_CANCEL_FILL && nextIcon != ICON_DOWNLOAD) {
|
|
float backProgress = (1.0f - Math.min(1.0f, transitionProgress / 0.5f));
|
|
//d *= backProgress;
|
|
alpha *= backProgress;
|
|
}
|
|
|
|
if (rotation != 0) {
|
|
canvas.save();
|
|
canvas.rotate(rotation, cx, cy);
|
|
}
|
|
if (alpha != 0) {
|
|
paint.setAlpha(alpha);
|
|
if (nextIcon == ICON_CANCEL_FILL) {
|
|
paint3.setAlpha(alpha);
|
|
rect.set(cx - AndroidUtilities.dp(3.5f), cy - AndroidUtilities.dp(3.5f), cx + AndroidUtilities.dp(3.5f), cy + AndroidUtilities.dp(3.5f));
|
|
canvas.drawRoundRect(rect, AndroidUtilities.dp(2), AndroidUtilities.dp(2), paint3);
|
|
|
|
paint.setAlpha((int) (alpha * 0.15f));
|
|
int diff = AndroidUtilities.dp(isMini ? 2 : 4);
|
|
rect.set(bounds.left + diff, bounds.top + diff, bounds.right - diff, bounds.bottom - diff);
|
|
canvas.drawArc(rect, 0, 360, false, paint);
|
|
paint.setAlpha(alpha);
|
|
} else {
|
|
canvas.drawLine(cx - d, cy - d, cx + d, cy + d, paint);
|
|
canvas.drawLine(cx + d, cy - d, cx - d, cy + d, paint);
|
|
}
|
|
}
|
|
if (rotation != 0) {
|
|
canvas.restore();
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
y1 = yStart;
|
|
y2 = yEnd;
|
|
x1 = cx - AndroidUtilities.dp(8) * scale;
|
|
x2 = cx + AndroidUtilities.dp(8) * scale;
|
|
y3 = y2 - AndroidUtilities.dp(8) * scale;
|
|
}
|
|
if (y1 != y2) {
|
|
canvas.drawLine(cx, y1, cx, y2, paint);
|
|
}
|
|
if (x1 != cx) {
|
|
canvas.drawLine(x1, y3, cx, y2, paint);
|
|
canvas.drawLine(x2, y3, cx, y2, paint);
|
|
}
|
|
}
|
|
|
|
if (currentIcon == ICON_CANCEL || currentIcon == ICON_CANCEL_FILL || currentIcon == ICON_NONE && (nextIcon == ICON_CANCEL_FILL || nextIcon == ICON_CANCEL)) {
|
|
applyShaderMatrix(false);
|
|
float d;
|
|
float rotation;
|
|
float iconScale = 1.0f, progressScale = 1.0f;
|
|
float iconScaleX = 0, progressScaleX = 0;
|
|
float iconScaleY = 0, progressScaleY = 0;
|
|
int alpha;
|
|
if (nextIcon == ICON_DOWNLOAD) {
|
|
if (transitionProgress <= DOWNLOAD_TO_CANCEL_STAGE3 + DOWNLOAD_TO_CANCEL_STAGE2) {
|
|
float progress = transitionProgress / (DOWNLOAD_TO_CANCEL_STAGE3 + DOWNLOAD_TO_CANCEL_STAGE2);
|
|
float backProgress = 1.0f - progress;
|
|
d = AndroidUtilities.dp(7) * backProgress * scale;
|
|
alpha = (int) (255 * backProgress);
|
|
} else {
|
|
d = 0;
|
|
alpha = 0;
|
|
}
|
|
rotation = 0;
|
|
} else if (nextIcon == ICON_UPDATE || nextIcon == ICON_PLAY || nextIcon == ICON_PAUSE || nextIcon == ICON_FILE || nextIcon == ICON_GIF || nextIcon == ICON_SECRETCHECK || nextIcon == ICON_FIRE || nextIcon == ICON_CHECK) {
|
|
float progress;
|
|
float backProgress;
|
|
if (nextIcon == ICON_CHECK) {
|
|
progress = Math.min(1.0f, transitionProgress / CANCEL_TO_CHECK_STAGE1);
|
|
} else {
|
|
progress = transitionProgress;
|
|
}
|
|
backProgress = 1.0f - progress;
|
|
rotation = 0;
|
|
progressScale = 1.0f;
|
|
iconScale = 1.0f - progress;
|
|
iconScaleX = progressScaleX = bounds.centerX();
|
|
iconScaleY = progressScaleY = bounds.centerY();
|
|
d = AndroidUtilities.dp(7) * backProgress * scale;
|
|
alpha = (int) (255 * Math.min(1.0f, backProgress * 2.0f));
|
|
} else if (nextIcon == ICON_NONE) {
|
|
float progress = transitionProgress;
|
|
float backProgress = 1.0f - progress;
|
|
d = AndroidUtilities.dp(7) * scale;
|
|
alpha = (int) (255 * backProgress);
|
|
rotation = 0;
|
|
iconScale = backProgress;
|
|
progressScale = 1f;
|
|
if (currentIcon == ICON_CANCEL_FILL) {
|
|
iconScaleX = progressScaleX = bounds.left;
|
|
iconScaleY = progressScaleY = bounds.top;
|
|
} else {
|
|
iconScaleX = progressScaleX = bounds.centerX();
|
|
iconScaleY = progressScaleY = bounds.centerY();
|
|
}
|
|
} else if (nextIcon == ICON_CANCEL_FILL || nextIcon == ICON_CANCEL) {
|
|
float progress = transitionProgress;
|
|
float backProgress = 1.0f - progress;
|
|
if (currentIcon == ICON_NONE) {
|
|
rotation = 0;
|
|
progressScale = 1.0f;
|
|
iconScale = progress;
|
|
} else {
|
|
rotation = 45 * backProgress;
|
|
iconScale = progressScale = 1.0f;
|
|
}
|
|
d = AndroidUtilities.dp(7) * scale;
|
|
alpha = (int) (255 * progress);
|
|
if (nextIcon == ICON_CANCEL_FILL) {
|
|
iconScaleX = progressScaleX = bounds.left;
|
|
iconScaleY = progressScaleY = bounds.top;
|
|
} else {
|
|
iconScaleX = progressScaleX = bounds.centerX();
|
|
iconScaleY = progressScaleY = bounds.centerY();
|
|
}
|
|
} else {
|
|
rotation = 0;
|
|
d = AndroidUtilities.dp(7) * scale;
|
|
alpha = 255;
|
|
}
|
|
if (iconScale != 1.0f) {
|
|
canvas.save();
|
|
canvas.scale(iconScale, iconScale, iconScaleX, iconScaleY);
|
|
}
|
|
if (rotation != 0) {
|
|
canvas.save();
|
|
canvas.rotate(rotation, cx, cy);
|
|
}
|
|
if (alpha != 0) {
|
|
paint.setAlpha((int) (alpha * overrideAlpha));
|
|
if (currentIcon == ICON_CANCEL_FILL || nextIcon == ICON_CANCEL_FILL) {
|
|
paint3.setAlpha((int) (alpha * overrideAlpha));
|
|
rect.set(cx - AndroidUtilities.dp(3.5f), cy - AndroidUtilities.dp(3.5f), cx + AndroidUtilities.dp(3.5f), cy + AndroidUtilities.dp(3.5f));
|
|
canvas.drawRoundRect(rect, AndroidUtilities.dp(2), AndroidUtilities.dp(2), paint3);
|
|
} else {
|
|
canvas.drawLine(cx - d, cy - d, cx + d, cy + d, paint);
|
|
canvas.drawLine(cx + d, cy - d, cx - d, cy + d, paint);
|
|
}
|
|
}
|
|
if (rotation != 0) {
|
|
canvas.restore();
|
|
}
|
|
if (iconScale != 1.0f) {
|
|
canvas.restore();
|
|
}
|
|
if (progressScale != 1.0f) {
|
|
canvas.save();
|
|
canvas.scale(progressScale, progressScale, progressScaleX, progressScaleY);
|
|
}
|
|
if ((currentIcon == ICON_CANCEL || currentIcon == ICON_CANCEL_FILL || currentIcon == ICON_NONE && (nextIcon == ICON_CANCEL_FILL || nextIcon == ICON_CANCEL)) && alpha != 0) {
|
|
float rad = Math.max(4, 360 * animatedDownloadProgress);
|
|
int diff = AndroidUtilities.dp(isMini ? 2 : 4);
|
|
rect.set(bounds.left + diff, bounds.top + diff, bounds.right - diff, bounds.bottom - diff);
|
|
|
|
if (currentIcon == ICON_CANCEL_FILL || currentIcon == ICON_NONE && nextIcon == ICON_CANCEL_FILL) {
|
|
paint.setAlpha((int) (alpha * 0.15f * overrideAlpha));
|
|
canvas.drawArc(rect, 0, 360, false, paint);
|
|
paint.setAlpha(alpha);
|
|
}
|
|
canvas.drawArc(rect, downloadRadOffset, rad, false, paint);
|
|
}
|
|
if (progressScale != 1.0f) {
|
|
canvas.restore();
|
|
}
|
|
} else if (currentIcon == ICON_EMPTY || nextIcon == ICON_EMPTY || currentIcon == ICON_CANCEL_PERCENT) {
|
|
int alpha;
|
|
if (nextIcon == ICON_NONE || nextIcon == ICON_CHECK) {
|
|
float progress = transitionProgress;
|
|
float backProgress = 1.0f - progress;
|
|
alpha = (int) (255 * backProgress);
|
|
} else {
|
|
alpha = 255;
|
|
}
|
|
|
|
if (alpha != 0) {
|
|
applyShaderMatrix(false);
|
|
paint.setAlpha((int) (alpha * overrideAlpha));
|
|
float rad = Math.max(4, 360 * animatedDownloadProgress);
|
|
int diff = AndroidUtilities.dp(isMini ? 2 : 4);
|
|
rect.set(bounds.left + diff, bounds.top + diff, bounds.right - diff, bounds.bottom - diff);
|
|
canvas.drawArc(rect, downloadRadOffset, rad, false, paint);
|
|
}
|
|
}
|
|
|
|
Drawable nextDrawable = null;
|
|
Drawable previousDrawable = null;
|
|
Path[] nextPath = null;
|
|
Path[] previousPath = null;
|
|
|
|
float drawableScale;
|
|
float previowsDrawableScale;
|
|
if (currentIcon == nextIcon) {
|
|
drawableScale = previowsDrawableScale = 1.0f;
|
|
} else if (currentIcon == ICON_NONE || currentIcon == ICON_CANCEL || currentIcon == ICON_CANCEL_FILL) {
|
|
drawableScale = transitionProgress;
|
|
previowsDrawableScale = 1.0f - transitionProgress;
|
|
} else {
|
|
drawableScale = Math.min(1.0f, transitionProgress / 0.5f);
|
|
previowsDrawableScale = Math.max(0.0f, 1.0f - transitionProgress / 0.5f);
|
|
}
|
|
|
|
if (nextIcon == ICON_UPDATE) {
|
|
nextPath = Theme.chat_updatePath;
|
|
} else if (currentIcon == ICON_UPDATE) {
|
|
previousPath = Theme.chat_updatePath;
|
|
}
|
|
if (nextIcon == ICON_FILE) {
|
|
nextPath = Theme.chat_filePath;
|
|
} else if (currentIcon == ICON_FILE) {
|
|
previousPath = Theme.chat_filePath;
|
|
}
|
|
if (nextIcon == ICON_FIRE) {
|
|
nextDrawable = Theme.chat_flameIcon;
|
|
} else if (currentIcon == ICON_FIRE) {
|
|
previousDrawable = Theme.chat_flameIcon;
|
|
}
|
|
if (nextIcon == ICON_GIF) {
|
|
nextDrawable = Theme.chat_gifIcon;
|
|
} else if (currentIcon == ICON_GIF) {
|
|
previousDrawable = Theme.chat_gifIcon;
|
|
}
|
|
|
|
|
|
if (currentIcon == ICON_SECRETCHECK || nextIcon == ICON_SECRETCHECK) {
|
|
applyShaderMatrix(false);
|
|
paint.setAlpha(currentIcon == nextIcon ? 255 : (int) (transitionProgress * 255));
|
|
int y = cy + AndroidUtilities.dp(7);
|
|
int x = cx - AndroidUtilities.dp(3);
|
|
if (currentIcon != nextIcon) {
|
|
canvas.save();
|
|
canvas.scale(transitionProgress, transitionProgress, cx, cy);
|
|
}
|
|
canvas.drawLine(x - AndroidUtilities.dp(6), y - AndroidUtilities.dp(6), x, y, paint);
|
|
canvas.drawLine(x, y, x + AndroidUtilities.dp(12), y - AndroidUtilities.dp(12), paint);
|
|
if (currentIcon != nextIcon) {
|
|
canvas.restore();
|
|
}
|
|
}
|
|
if (currentIcon == ICON_CANCEL_NOPROFRESS || nextIcon == ICON_CANCEL_NOPROFRESS) {
|
|
applyShaderMatrix(false);
|
|
float transition;
|
|
if (currentIcon == nextIcon) {
|
|
transition = 1.0f;
|
|
} else if (nextIcon == ICON_CANCEL_PERCENT) {
|
|
transition = transitionProgress;
|
|
} else {
|
|
transition = 1.0f - transitionProgress;
|
|
}
|
|
|
|
paint.setAlpha(currentIcon == nextIcon ? 255 : (int) (transition * 255));
|
|
int y = cy + AndroidUtilities.dp(7);
|
|
int x = cx - AndroidUtilities.dp(3);
|
|
if (currentIcon != nextIcon) {
|
|
canvas.save();
|
|
canvas.scale(transition, transition, cx, cy);
|
|
}
|
|
|
|
float d = AndroidUtilities.dp(7) * scale;
|
|
canvas.drawLine(cx - d, cy - d, cx + d, cy + d, paint);
|
|
canvas.drawLine(cx + d, cy - d, cx - d, cy + d, paint);
|
|
|
|
if (currentIcon != nextIcon) {
|
|
canvas.restore();
|
|
}
|
|
}
|
|
if (currentIcon == ICON_CANCEL_PERCENT || nextIcon == ICON_CANCEL_PERCENT) {
|
|
applyShaderMatrix(false);
|
|
float transition;
|
|
if (currentIcon == nextIcon) {
|
|
transition = 1.0f;
|
|
} else if (nextIcon == ICON_CANCEL_PERCENT) {
|
|
transition = transitionProgress;
|
|
} else {
|
|
transition = 1.0f - transitionProgress;
|
|
}
|
|
|
|
textPaint.setAlpha((int) (transition * 255));
|
|
int y = cy + AndroidUtilities.dp(5);
|
|
int x = cx - percentStringWidth / 2;
|
|
if (currentIcon != nextIcon) {
|
|
canvas.save();
|
|
canvas.scale(transition, transition, cx, cy);
|
|
}
|
|
int newPercent = (int) (animatedDownloadProgress * 100);
|
|
if (percentString == null || newPercent != lastPercent) {
|
|
lastPercent = newPercent;
|
|
percentString = String.format("%d%%", lastPercent);
|
|
percentStringWidth = (int) Math.ceil(textPaint.measureText(percentString));
|
|
}
|
|
canvas.drawText(percentString, x, y, textPaint);
|
|
if (currentIcon != nextIcon) {
|
|
canvas.restore();
|
|
}
|
|
}
|
|
if (currentIcon == ICON_PLAY || currentIcon == ICON_PAUSE || nextIcon == ICON_PLAY || nextIcon == ICON_PAUSE) {
|
|
float p;
|
|
if (currentIcon == ICON_PLAY && nextIcon == ICON_PAUSE || currentIcon == ICON_PAUSE && nextIcon == ICON_PLAY) {
|
|
if (animatingTransition) {
|
|
if (nextIcon == ICON_PLAY) {
|
|
p = 1.0f - transitionProgress;
|
|
} else {
|
|
p = transitionProgress;
|
|
}
|
|
} else {
|
|
p = nextIcon == ICON_PAUSE ? 1.0f : 0.0f;
|
|
}
|
|
} else {
|
|
p = currentIcon == ICON_PAUSE ? 1.0f : 0.0f;
|
|
}
|
|
|
|
if (nextIcon != ICON_PLAY && nextIcon != ICON_PAUSE || currentIcon != ICON_PLAY && currentIcon != ICON_PAUSE) {
|
|
if (nextIcon == ICON_NONE) {
|
|
paint2.setAlpha((int) (255 * (1.0f - transitionProgress)));
|
|
} else {
|
|
paint2.setAlpha(currentIcon == nextIcon ? 255 : (int) (transitionProgress * 255));
|
|
}
|
|
} else {
|
|
paint2.setAlpha(255);
|
|
}
|
|
|
|
applyShaderMatrix(true);
|
|
|
|
canvas.save();
|
|
canvas.translate(bounds.centerX() + AndroidUtilities.dp(1) * (1.0f - p), bounds.centerY());
|
|
float ms = 500.0f * p;
|
|
float rotation = currentIcon == ICON_PAUSE ? 90 : 0;
|
|
if (currentIcon == ICON_PLAY && nextIcon == ICON_PAUSE) {
|
|
if (ms < 384) {
|
|
rotation = 95 * CubicBezierInterpolator.EASE_BOTH.getInterpolation(ms / 384);
|
|
} else if (ms < 484) {
|
|
rotation = 95 - 5 * CubicBezierInterpolator.EASE_BOTH.getInterpolation((ms - 384) / 100.0f);
|
|
} else {
|
|
rotation = 90;
|
|
}
|
|
ms += 100;
|
|
} else if (currentIcon == ICON_PAUSE && nextIcon == ICON_PLAY) {
|
|
if (ms < 100) {
|
|
rotation = -5 * CubicBezierInterpolator.EASE_BOTH.getInterpolation(ms / 100.0f);
|
|
} else if (ms < 484) {
|
|
rotation = -5 + 95 * CubicBezierInterpolator.EASE_BOTH.getInterpolation((ms - 100) / 384);
|
|
} else {
|
|
rotation = 90;
|
|
}
|
|
}
|
|
canvas.rotate(rotation);
|
|
if (currentIcon != ICON_PLAY && currentIcon != ICON_PAUSE || currentIcon == ICON_NONE) {
|
|
canvas.scale(drawableScale, drawableScale);
|
|
}
|
|
Theme.playPauseAnimator.draw(canvas, paint2, ms);
|
|
canvas.scale(1.0f, -1.0f);
|
|
Theme.playPauseAnimator.draw(canvas, paint2, ms);
|
|
|
|
canvas.restore();
|
|
}
|
|
if (currentIcon == ICON_CHECK || nextIcon == ICON_CHECK) {
|
|
applyShaderMatrix(false);
|
|
float progress1;
|
|
float progress2;
|
|
if (currentIcon != ICON_CHECK) {
|
|
if (transitionProgress > CANCEL_TO_CHECK_STAGE1) {
|
|
float progress = (transitionProgress - CANCEL_TO_CHECK_STAGE1) / CANCEL_TO_CHECK_STAGE2;
|
|
progress1 = 1.0f - Math.min(1.0f, progress / 0.5f);
|
|
progress2 = progress > 0.5f ? ((progress - 0.5f) / 0.5f) : 0.0f;
|
|
} else {
|
|
progress1 = 1.0f;
|
|
progress2 = 0.0f;
|
|
}
|
|
paint.setAlpha(255);
|
|
} else {
|
|
progress1 = 0.0f;
|
|
progress2 = 1.0f;
|
|
if (nextIcon != ICON_CHECK) {
|
|
paint.setAlpha((int) (255 * (1.0f - transitionProgress)));
|
|
} else {
|
|
paint.setAlpha(255);
|
|
}
|
|
}
|
|
int y = cy + AndroidUtilities.dp(7);
|
|
int x = cx - AndroidUtilities.dp(3);
|
|
if (progress1 < 1) {
|
|
canvas.drawLine(x - AndroidUtilities.dp(6), y - AndroidUtilities.dp(6), x - AndroidUtilities.dp(6) * progress1, y - AndroidUtilities.dp(6) * progress1, paint);
|
|
}
|
|
if (progress2 > 0) {
|
|
canvas.drawLine(x, y, x + AndroidUtilities.dp(12) * progress2, y - AndroidUtilities.dp(12) * progress2, paint);
|
|
}
|
|
}
|
|
|
|
if (previousDrawable != null && previousDrawable != nextDrawable) {
|
|
int w = (int) (previousDrawable.getIntrinsicWidth() * previowsDrawableScale);
|
|
int h = (int) (previousDrawable.getIntrinsicHeight() * previowsDrawableScale);
|
|
previousDrawable.setColorFilter(colorFilter);
|
|
previousDrawable.setAlpha(currentIcon == nextIcon ? 255 : (int) ((1.0f - transitionProgress) * 255));
|
|
previousDrawable.setBounds(cx - w / 2, cy - h / 2, cx + w / 2, cy + h / 2);
|
|
previousDrawable.draw(canvas);
|
|
}
|
|
if (nextDrawable != null) {
|
|
int w = (int) (nextDrawable.getIntrinsicWidth() * drawableScale);
|
|
int h = (int) (nextDrawable.getIntrinsicHeight() * drawableScale);
|
|
nextDrawable.setColorFilter(colorFilter);
|
|
nextDrawable.setAlpha(currentIcon == nextIcon ? 255 : (int) (transitionProgress * 255));
|
|
nextDrawable.setBounds(cx - w / 2, cy - h / 2, cx + w / 2, cy + h / 2);
|
|
nextDrawable.draw(canvas);
|
|
}
|
|
|
|
if (previousPath != null && previousPath != nextPath) {
|
|
int size = AndroidUtilities.dp(24);
|
|
paint2.setStyle(Paint.Style.FILL_AND_STROKE);
|
|
paint2.setAlpha(currentIcon == nextIcon ? 255 : (int) ((1.0f - transitionProgress) * 255));
|
|
applyShaderMatrix(true);
|
|
canvas.save();
|
|
canvas.translate(cx, cy);
|
|
canvas.scale(previowsDrawableScale, previowsDrawableScale);
|
|
canvas.translate(-size / 2, -size / 2);
|
|
if (previousPath[0] != null) {
|
|
canvas.drawPath(previousPath[0], paint2);
|
|
}
|
|
if (previousPath[1] != null) {
|
|
canvas.drawPath(previousPath[1], backPaint);
|
|
}
|
|
canvas.restore();
|
|
}
|
|
if (nextPath != null) {
|
|
int size = AndroidUtilities.dp(24);
|
|
int alpha = currentIcon == nextIcon ? 255 : (int) (transitionProgress * 255);
|
|
paint2.setStyle(Paint.Style.FILL_AND_STROKE);
|
|
paint2.setAlpha(alpha);
|
|
applyShaderMatrix(true);
|
|
canvas.save();
|
|
canvas.translate(cx, cy);
|
|
canvas.scale(drawableScale, drawableScale);
|
|
canvas.translate(-size / 2, -size / 2);
|
|
if (nextPath[0] != null) {
|
|
canvas.drawPath(nextPath[0], paint2);
|
|
}
|
|
if (nextPath.length >= 3 && nextPath[2] != null) {
|
|
canvas.drawPath(nextPath[2], paint);
|
|
}
|
|
if (nextPath[1] != null) {
|
|
if (alpha != 255) {
|
|
int backgroundAlpha = backPaint.getAlpha();
|
|
backPaint.setAlpha((int) (backgroundAlpha * (alpha / 255f)));
|
|
canvas.drawPath(nextPath[1], backPaint);
|
|
backPaint.setAlpha(backgroundAlpha);
|
|
} else {
|
|
canvas.drawPath(nextPath[1], backPaint);
|
|
}
|
|
}
|
|
canvas.restore();
|
|
}
|
|
|
|
long newTime = System.currentTimeMillis();
|
|
long dt = newTime - lastAnimationTime;
|
|
if (dt > 17) {
|
|
dt = 17;
|
|
}
|
|
lastAnimationTime = newTime;
|
|
|
|
if (currentIcon == ICON_CANCEL || currentIcon == ICON_CANCEL_FILL || currentIcon == ICON_NONE && nextIcon == ICON_CANCEL_FILL || currentIcon == ICON_EMPTY || currentIcon == ICON_CANCEL_PERCENT) {
|
|
downloadRadOffset += 360 * dt / 2500.0f;
|
|
downloadRadOffset = getCircleValue(downloadRadOffset);
|
|
|
|
if (nextIcon != ICON_DOWNLOAD) {
|
|
float progressDiff = downloadProgress - downloadProgressAnimationStart;
|
|
if (progressDiff > 0) {
|
|
downloadProgressTime += dt;
|
|
if (downloadProgressTime >= 200.0f) {
|
|
animatedDownloadProgress = downloadProgress;
|
|
downloadProgressAnimationStart = downloadProgress;
|
|
downloadProgressTime = 0;
|
|
} else {
|
|
animatedDownloadProgress = downloadProgressAnimationStart + progressDiff * interpolator.getInterpolation(downloadProgressTime / 200.0f);
|
|
}
|
|
}
|
|
}
|
|
invalidateSelf();
|
|
}
|
|
|
|
if (animatingTransition) {
|
|
if (transitionProgress < 1.0f) {
|
|
transitionProgress += dt / transitionAnimationTime;
|
|
if (transitionProgress >= 1.0f) {
|
|
currentIcon = nextIcon;
|
|
transitionProgress = 1.0f;
|
|
animatingTransition = false;
|
|
}
|
|
invalidateSelf();
|
|
}
|
|
}
|
|
if (saveCount >= 1) {
|
|
canvas.restoreToCount(saveCount);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public int getIntrinsicWidth() {
|
|
return AndroidUtilities.dp(48);
|
|
}
|
|
|
|
@Override
|
|
public int getIntrinsicHeight() {
|
|
return AndroidUtilities.dp(48);
|
|
}
|
|
|
|
@Override
|
|
public int getMinimumWidth() {
|
|
return AndroidUtilities.dp(48);
|
|
}
|
|
|
|
@Override
|
|
public int getMinimumHeight() {
|
|
return AndroidUtilities.dp(48);
|
|
}
|
|
}
|