mirror of https://github.com/NekoX-Dev/NekoX.git
508 lines
20 KiB
Java
508 lines
20 KiB
Java
/*
|
|
* This is the source code of Telegram for Android v. 2.0.x.
|
|
* It is licensed under GNU GPL v. 2 or later.
|
|
* You should have received a copy of the license in this archive (see LICENSE).
|
|
*
|
|
* Copyright Nikolai Kudashov, 2013-2018.
|
|
*/
|
|
|
|
package org.telegram.ui.Components;
|
|
|
|
import android.graphics.Bitmap;
|
|
import android.graphics.Canvas;
|
|
import android.graphics.ColorFilter;
|
|
import android.graphics.Paint;
|
|
import android.graphics.PixelFormat;
|
|
import android.graphics.RectF;
|
|
import android.graphics.drawable.Drawable;
|
|
import android.view.View;
|
|
import android.view.animation.DecelerateInterpolator;
|
|
|
|
import org.telegram.messenger.AndroidUtilities;
|
|
import org.telegram.ui.ActionBar.Theme;
|
|
|
|
public class RadialProgress {
|
|
|
|
private long lastUpdateTime = 0;
|
|
private float radOffset = 0;
|
|
private float currentProgress = 0;
|
|
private float animationProgressStart = 0;
|
|
private long currentProgressTime = 0;
|
|
private float animatedProgressValue = 0;
|
|
private RectF progressRect = new RectF();
|
|
private RectF cicleRect = new RectF();
|
|
private View parent;
|
|
private float animatedAlphaValue = 1.0f;
|
|
|
|
private boolean previousCheckDrawable;
|
|
|
|
private boolean currentMiniWithRound;
|
|
private boolean previousMiniWithRound;
|
|
private boolean currentWithRound;
|
|
private boolean previousWithRound;
|
|
private Drawable currentMiniDrawable;
|
|
private Drawable previousMiniDrawable;
|
|
private Drawable currentDrawable;
|
|
private Drawable previousDrawable;
|
|
private boolean hideCurrentDrawable;
|
|
private int progressColor = 0xffffffff;
|
|
private Paint progressPaint;
|
|
private Paint miniProgressPaint;
|
|
private Paint miniProgressBackgroundPaint;
|
|
|
|
private boolean drawMiniProgress;
|
|
|
|
private CheckDrawable checkDrawable;
|
|
private Drawable checkBackgroundDrawable;
|
|
|
|
private int diff = AndroidUtilities.dp(4);
|
|
|
|
private static DecelerateInterpolator decelerateInterpolator;
|
|
private boolean alphaForPrevious = true;
|
|
private boolean alphaForMiniPrevious = true;
|
|
|
|
private Bitmap miniDrawBitmap;
|
|
private Canvas miniDrawCanvas;
|
|
|
|
private float overrideAlpha = 1.0f;
|
|
|
|
private class CheckDrawable extends Drawable {
|
|
|
|
private Paint paint;
|
|
private float progress;
|
|
|
|
public CheckDrawable() {
|
|
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
paint.setStyle(Paint.Style.STROKE);
|
|
paint.setStrokeWidth(AndroidUtilities.dp(3));
|
|
paint.setStrokeCap(Paint.Cap.ROUND);
|
|
paint.setColor(0xffffffff);
|
|
}
|
|
|
|
public void resetProgress(boolean animated) {
|
|
progress = animated ? 0.0f : 1.0f;
|
|
}
|
|
|
|
public boolean updateAnimation(long dt) {
|
|
if (progress < 1.0f) {
|
|
progress += dt / 700.0f;
|
|
if (progress > 1.0f) {
|
|
progress = 1.0f;
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public void draw(Canvas canvas) {
|
|
int x = getBounds().centerX() - AndroidUtilities.dp(12);
|
|
int y = getBounds().centerY() - AndroidUtilities.dp(6);
|
|
float p = progress != 1.0f ? decelerateInterpolator.getInterpolation(progress) : 1.0f;
|
|
int endX = (int) (AndroidUtilities.dp(7.0f) - AndroidUtilities.dp(6) * p);
|
|
int endY = (int) (AndroidUtilities.dpf2(13.0f) - AndroidUtilities.dp(6) * p);
|
|
canvas.drawLine(x + AndroidUtilities.dp(7.0f), y + (int) AndroidUtilities.dpf2(13.0f), x + endX, y + endY, paint);
|
|
endX = (int) (AndroidUtilities.dpf2(7.0f) + AndroidUtilities.dp(13) * p);
|
|
endY = (int) (AndroidUtilities.dpf2(13.0f) - AndroidUtilities.dp(13) * p);
|
|
canvas.drawLine(x + (int) AndroidUtilities.dpf2(7.0f), y + (int) AndroidUtilities.dpf2(13.0f), x + endX, y + endY, paint);
|
|
}
|
|
|
|
@Override
|
|
public void setAlpha(int alpha) {
|
|
paint.setAlpha(alpha);
|
|
}
|
|
|
|
@Override
|
|
public void setColorFilter(ColorFilter cf) {
|
|
paint.setColorFilter(cf);
|
|
}
|
|
|
|
@Override
|
|
public int getOpacity() {
|
|
return PixelFormat.TRANSPARENT;
|
|
}
|
|
|
|
@Override
|
|
public int getIntrinsicWidth() {
|
|
return AndroidUtilities.dp(48);
|
|
}
|
|
|
|
@Override
|
|
public int getIntrinsicHeight() {
|
|
return AndroidUtilities.dp(48);
|
|
}
|
|
}
|
|
|
|
public RadialProgress(View parentView) {
|
|
if (decelerateInterpolator == null) {
|
|
decelerateInterpolator = new DecelerateInterpolator();
|
|
}
|
|
progressPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
progressPaint.setStyle(Paint.Style.STROKE);
|
|
progressPaint.setStrokeCap(Paint.Cap.ROUND);
|
|
progressPaint.setStrokeWidth(AndroidUtilities.dp(3));
|
|
|
|
miniProgressPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
miniProgressPaint.setStyle(Paint.Style.STROKE);
|
|
miniProgressPaint.setStrokeCap(Paint.Cap.ROUND);
|
|
miniProgressPaint.setStrokeWidth(AndroidUtilities.dp(2));
|
|
|
|
miniProgressBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
|
|
parent = parentView;
|
|
}
|
|
|
|
public void setStrokeWidth(int width) {
|
|
progressPaint.setStrokeWidth(width);
|
|
}
|
|
|
|
public void setProgressRect(int left, int top, int right, int bottom) {
|
|
progressRect.set(left, top, right, bottom);
|
|
}
|
|
|
|
public RectF getProgressRect() {
|
|
return progressRect;
|
|
}
|
|
|
|
public void setAlphaForPrevious(boolean value) {
|
|
alphaForPrevious = value;
|
|
}
|
|
|
|
public void setAlphaForMiniPrevious(boolean value) {
|
|
alphaForMiniPrevious = value;
|
|
}
|
|
|
|
private void updateAnimation(boolean progress) {
|
|
long newTime = System.currentTimeMillis();
|
|
long dt = newTime - lastUpdateTime;
|
|
lastUpdateTime = newTime;
|
|
if (checkBackgroundDrawable != null && (currentDrawable == checkBackgroundDrawable || previousDrawable == checkBackgroundDrawable)) {
|
|
if (checkDrawable.updateAnimation(dt)) {
|
|
invalidateParent();
|
|
}
|
|
}
|
|
|
|
if (progress) {
|
|
if (animatedProgressValue != 1) {
|
|
radOffset += 360 * dt / 3000.0f;
|
|
float progressDiff = currentProgress - animationProgressStart;
|
|
if (progressDiff > 0) {
|
|
currentProgressTime += dt;
|
|
if (currentProgressTime >= 300) {
|
|
animatedProgressValue = currentProgress;
|
|
animationProgressStart = currentProgress;
|
|
currentProgressTime = 0;
|
|
} else {
|
|
animatedProgressValue = animationProgressStart + progressDiff * decelerateInterpolator.getInterpolation(currentProgressTime / 300.0f);
|
|
}
|
|
}
|
|
invalidateParent();
|
|
}
|
|
if (drawMiniProgress) {
|
|
if (animatedProgressValue >= 1 && previousMiniDrawable != null) {
|
|
animatedAlphaValue -= dt / 200.0f;
|
|
if (animatedAlphaValue <= 0) {
|
|
animatedAlphaValue = 0.0f;
|
|
previousMiniDrawable = null;
|
|
drawMiniProgress = currentMiniDrawable != null;
|
|
}
|
|
invalidateParent();
|
|
}
|
|
} else {
|
|
if (animatedProgressValue >= 1 && previousDrawable != null) {
|
|
animatedAlphaValue -= dt / 200.0f;
|
|
if (animatedAlphaValue <= 0) {
|
|
animatedAlphaValue = 0.0f;
|
|
previousDrawable = null;
|
|
}
|
|
invalidateParent();
|
|
}
|
|
}
|
|
} else {
|
|
if (drawMiniProgress) {
|
|
if (previousMiniDrawable != null) {
|
|
animatedAlphaValue -= dt / 200.0f;
|
|
if (animatedAlphaValue <= 0) {
|
|
animatedAlphaValue = 0.0f;
|
|
previousMiniDrawable = null;
|
|
drawMiniProgress = currentMiniDrawable != null;
|
|
}
|
|
invalidateParent();
|
|
}
|
|
} else {
|
|
if (previousDrawable != null) {
|
|
animatedAlphaValue -= dt / 200.0f;
|
|
if (animatedAlphaValue <= 0) {
|
|
animatedAlphaValue = 0.0f;
|
|
previousDrawable = null;
|
|
}
|
|
invalidateParent();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void setDiff(int value) {
|
|
diff = value;
|
|
}
|
|
|
|
public void setProgressColor(int color) {
|
|
progressColor = color;
|
|
}
|
|
|
|
public void setMiniProgressBackgroundColor(int color) {
|
|
miniProgressBackgroundPaint.setColor(color);
|
|
}
|
|
|
|
public void setHideCurrentDrawable(boolean value) {
|
|
hideCurrentDrawable = value;
|
|
}
|
|
|
|
public void setProgress(float value, boolean animated) {
|
|
if (drawMiniProgress) {
|
|
if (value != 1 && animatedAlphaValue != 0 && previousMiniDrawable != null) {
|
|
animatedAlphaValue = 0.0f;
|
|
previousMiniDrawable = null;
|
|
drawMiniProgress = currentMiniDrawable != null;
|
|
}
|
|
} else {
|
|
if (value != 1 && animatedAlphaValue != 0 && previousDrawable != null) {
|
|
animatedAlphaValue = 0.0f;
|
|
previousDrawable = null;
|
|
}
|
|
}
|
|
if (!animated) {
|
|
animatedProgressValue = value;
|
|
animationProgressStart = value;
|
|
} else {
|
|
if (animatedProgressValue > value) {
|
|
animatedProgressValue = value;
|
|
}
|
|
animationProgressStart = animatedProgressValue;
|
|
}
|
|
currentProgress = value;
|
|
currentProgressTime = 0;
|
|
|
|
invalidateParent();
|
|
}
|
|
|
|
private void invalidateParent() {
|
|
int offset = AndroidUtilities.dp(2);
|
|
parent.invalidate((int) progressRect.left - offset, (int) progressRect.top - offset, (int) progressRect.right + offset * 2, (int) progressRect.bottom + offset * 2);
|
|
}
|
|
|
|
public void setCheckBackground(boolean withRound, boolean animated) {
|
|
if (checkDrawable == null) {
|
|
checkDrawable = new CheckDrawable();
|
|
checkBackgroundDrawable = Theme.createCircleDrawableWithIcon(AndroidUtilities.dp(48), checkDrawable, 0);
|
|
}
|
|
Theme.setCombinedDrawableColor(checkBackgroundDrawable, Theme.getColor(Theme.key_chat_mediaLoaderPhoto), false);
|
|
Theme.setCombinedDrawableColor(checkBackgroundDrawable, Theme.getColor(Theme.key_chat_mediaLoaderPhotoIcon), true);
|
|
if (currentDrawable != checkBackgroundDrawable) {
|
|
setBackground(checkBackgroundDrawable, withRound, animated);
|
|
checkDrawable.resetProgress(animated);
|
|
}
|
|
}
|
|
|
|
public boolean isDrawCheckDrawable() {
|
|
return currentDrawable == checkBackgroundDrawable;
|
|
}
|
|
|
|
public void setBackground(Drawable drawable, boolean withRound, boolean animated) {
|
|
lastUpdateTime = System.currentTimeMillis();
|
|
if (animated && currentDrawable != drawable) {
|
|
previousDrawable = currentDrawable;
|
|
previousWithRound = currentWithRound;
|
|
animatedAlphaValue = 1.0f;
|
|
setProgress(1, animated);
|
|
} else {
|
|
previousDrawable = null;
|
|
previousWithRound = false;
|
|
}
|
|
currentWithRound = withRound;
|
|
currentDrawable = drawable;
|
|
if (!animated) {
|
|
parent.invalidate();
|
|
} else {
|
|
invalidateParent();
|
|
}
|
|
}
|
|
|
|
public void setMiniBackground(Drawable drawable, boolean withRound, boolean animated) {
|
|
lastUpdateTime = System.currentTimeMillis();
|
|
if (animated && currentMiniDrawable != drawable) {
|
|
previousMiniDrawable = currentMiniDrawable;
|
|
previousMiniWithRound = currentMiniWithRound;
|
|
animatedAlphaValue = 1.0f;
|
|
setProgress(1, animated);
|
|
} else {
|
|
previousMiniDrawable = null;
|
|
previousMiniWithRound = false;
|
|
}
|
|
currentMiniWithRound = withRound;
|
|
currentMiniDrawable = drawable;
|
|
drawMiniProgress = previousMiniDrawable != null || currentMiniDrawable != null;
|
|
if (drawMiniProgress && miniDrawBitmap == null) {
|
|
try {
|
|
miniDrawBitmap = Bitmap.createBitmap(AndroidUtilities.dp(48), AndroidUtilities.dp(48), Bitmap.Config.ARGB_8888);
|
|
miniDrawCanvas = new Canvas(miniDrawBitmap);
|
|
} catch (Throwable ignore) {
|
|
|
|
}
|
|
}
|
|
if (!animated) {
|
|
parent.invalidate();
|
|
} else {
|
|
invalidateParent();
|
|
}
|
|
}
|
|
|
|
public boolean swapBackground(Drawable drawable) {
|
|
if (currentDrawable != drawable) {
|
|
currentDrawable = drawable;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public boolean swapMiniBackground(Drawable drawable) {
|
|
if (currentMiniDrawable != drawable) {
|
|
currentMiniDrawable = drawable;
|
|
drawMiniProgress = previousMiniDrawable != null || currentMiniDrawable != null;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public float getAlpha() {
|
|
return previousDrawable != null || currentDrawable != null ? animatedAlphaValue : 0.0f;
|
|
}
|
|
|
|
public void setOverrideAlpha(float alpha) {
|
|
overrideAlpha = alpha;
|
|
}
|
|
|
|
public void draw(Canvas canvas) {
|
|
if (drawMiniProgress && currentDrawable != null) {
|
|
if (miniDrawCanvas != null) {
|
|
miniDrawBitmap.eraseColor(0);
|
|
}
|
|
|
|
currentDrawable.setAlpha((int) (255 * overrideAlpha));
|
|
if (miniDrawCanvas != null) {
|
|
currentDrawable.setBounds(0, 0, (int) progressRect.width(), (int) progressRect.height());
|
|
currentDrawable.draw(miniDrawCanvas);
|
|
} else {
|
|
currentDrawable.setBounds((int) progressRect.left, (int) progressRect.top, (int) progressRect.right, (int) progressRect.bottom);
|
|
currentDrawable.draw(canvas);
|
|
}
|
|
|
|
int offset;
|
|
int size;
|
|
float cx;
|
|
float cy;
|
|
if (Math.abs(progressRect.width() - AndroidUtilities.dp(44)) < AndroidUtilities.density) {
|
|
offset = 0;
|
|
size = 20;
|
|
cx = progressRect.centerX() + AndroidUtilities.dp(16 + offset);
|
|
cy = progressRect.centerY() + AndroidUtilities.dp(16 + offset);
|
|
} else {
|
|
offset = 2;
|
|
size = 22;
|
|
cx = progressRect.centerX() + AndroidUtilities.dp(18);
|
|
cy = progressRect.centerY() + AndroidUtilities.dp(18);
|
|
}
|
|
int halfSize = size / 2;
|
|
|
|
float alpha = 1.0f;
|
|
if (previousMiniDrawable != null && alphaForMiniPrevious) {
|
|
alpha = animatedAlphaValue * overrideAlpha;
|
|
}
|
|
|
|
if (miniDrawCanvas != null) {
|
|
miniDrawCanvas.drawCircle(AndroidUtilities.dp(18 + size + offset), AndroidUtilities.dp(18 + size + offset), AndroidUtilities.dp(halfSize + 1) * alpha, Theme.checkboxSquare_eraserPaint);
|
|
} else {
|
|
miniProgressBackgroundPaint.setColor(progressColor);
|
|
if (previousMiniDrawable != null && currentMiniDrawable == null) {
|
|
miniProgressBackgroundPaint.setAlpha((int) (255 * animatedAlphaValue * overrideAlpha));
|
|
} else {
|
|
miniProgressBackgroundPaint.setAlpha(255);
|
|
}
|
|
canvas.drawCircle(cx, cy, AndroidUtilities.dp(12), miniProgressBackgroundPaint);
|
|
}
|
|
|
|
if (miniDrawCanvas != null) {
|
|
canvas.drawBitmap(miniDrawBitmap, (int) progressRect.left, (int) progressRect.top, null);
|
|
}
|
|
|
|
if (previousMiniDrawable != null) {
|
|
if (alphaForMiniPrevious) {
|
|
previousMiniDrawable.setAlpha((int) (255 * animatedAlphaValue * overrideAlpha));
|
|
} else {
|
|
previousMiniDrawable.setAlpha((int) (255 * overrideAlpha));
|
|
}
|
|
previousMiniDrawable.setBounds((int) (cx - AndroidUtilities.dp(halfSize) * alpha), (int) (cy - AndroidUtilities.dp(halfSize) * alpha), (int) (cx + AndroidUtilities.dp(halfSize) * alpha), (int) (cy + AndroidUtilities.dp(halfSize) * alpha));
|
|
previousMiniDrawable.draw(canvas);
|
|
}
|
|
|
|
if (!hideCurrentDrawable && currentMiniDrawable != null) {
|
|
if (previousMiniDrawable != null) {
|
|
currentMiniDrawable.setAlpha((int) (255 * (1.0f - animatedAlphaValue) * overrideAlpha));
|
|
} else {
|
|
currentMiniDrawable.setAlpha((int) (255 * overrideAlpha));
|
|
}
|
|
currentMiniDrawable.setBounds((int) (cx - AndroidUtilities.dp(halfSize)), (int) (cy - AndroidUtilities.dp(halfSize)), (int) (cx + AndroidUtilities.dp(halfSize)), (int) (cy + AndroidUtilities.dp(halfSize)));
|
|
currentMiniDrawable.draw(canvas);
|
|
}
|
|
|
|
if (currentMiniWithRound || previousMiniWithRound) {
|
|
miniProgressPaint.setColor(progressColor);
|
|
if (previousMiniWithRound) {
|
|
miniProgressPaint.setAlpha((int) (255 * animatedAlphaValue * overrideAlpha));
|
|
} else {
|
|
miniProgressPaint.setAlpha((int) (255 * overrideAlpha));
|
|
}
|
|
cicleRect.set(cx - AndroidUtilities.dp(halfSize - 2) * alpha, cy - AndroidUtilities.dp(halfSize - 2) * alpha, cx + AndroidUtilities.dp(halfSize - 2) * alpha, cy + AndroidUtilities.dp(halfSize - 2) * alpha);
|
|
canvas.drawArc(cicleRect, -90 + radOffset, Math.max(4, 360 * animatedProgressValue), false, miniProgressPaint);
|
|
updateAnimation(true);
|
|
} else {
|
|
updateAnimation(false);
|
|
}
|
|
} else {
|
|
if (previousDrawable != null) {
|
|
if (alphaForPrevious) {
|
|
previousDrawable.setAlpha((int) (255 * animatedAlphaValue * overrideAlpha));
|
|
} else {
|
|
previousDrawable.setAlpha((int) (255 * overrideAlpha));
|
|
}
|
|
previousDrawable.setBounds((int) progressRect.left, (int) progressRect.top, (int) progressRect.right, (int) progressRect.bottom);
|
|
previousDrawable.draw(canvas);
|
|
}
|
|
|
|
if (!hideCurrentDrawable && currentDrawable != null) {
|
|
if (previousDrawable != null) {
|
|
currentDrawable.setAlpha((int) (255 * (1.0f - animatedAlphaValue) * overrideAlpha));
|
|
} else {
|
|
currentDrawable.setAlpha((int) (255 * overrideAlpha));
|
|
}
|
|
currentDrawable.setBounds((int) progressRect.left, (int) progressRect.top, (int) progressRect.right, (int) progressRect.bottom);
|
|
currentDrawable.draw(canvas);
|
|
}
|
|
|
|
if (currentWithRound || previousWithRound) {
|
|
progressPaint.setColor(progressColor);
|
|
if (previousWithRound) {
|
|
progressPaint.setAlpha((int) (255 * animatedAlphaValue * overrideAlpha));
|
|
} else {
|
|
progressPaint.setAlpha((int) (255 * overrideAlpha));
|
|
}
|
|
cicleRect.set(progressRect.left + diff, progressRect.top + diff, progressRect.right - diff, progressRect.bottom - diff);
|
|
canvas.drawArc(cicleRect, -90 + radOffset, Math.max(4, 360 * animatedProgressValue), false, progressPaint);
|
|
updateAnimation(true);
|
|
} else {
|
|
updateAnimation(false);
|
|
}
|
|
}
|
|
}
|
|
}
|