NekoX/TMessagesProj/src/main/java/org/telegram/ui/VoiceMessageEnterTransition...

175 lines
6.9 KiB
Java

package org.telegram.ui;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Shader;
import android.transition.Transition;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.widget.FrameLayout;
import androidx.core.graphics.ColorUtils;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Cells.ChatMessageCell;
import org.telegram.ui.Components.ChatActivityEnterView;
import org.telegram.ui.Components.CubicBezierInterpolator;
import org.telegram.ui.Components.RecyclerListView;
public class VoiceMessageEnterTransition implements MessageEnterTransitionContainer.Transition {
private final ChatMessageCell messageView;
private final RecyclerListView listView;
float fromRadius;
float progress;
final Paint circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final ValueAnimator animator;
private final ChatActivityEnterView.RecordCircle recordCircle;
private final Matrix gradientMatrix;
private final Paint gradientPaint;
private final LinearGradient gradientShader;
private final int messageId;
MessageEnterTransitionContainer container;
private final Theme.ResourcesProvider resourcesProvider;
public VoiceMessageEnterTransition(ChatMessageCell messageView, ChatActivityEnterView chatActivityEnterView, RecyclerListView listView, MessageEnterTransitionContainer container, Theme.ResourcesProvider resourcesProvider) {
this.resourcesProvider = resourcesProvider;
this.messageView = messageView;
this.container = container;
this.listView = listView;
fromRadius = chatActivityEnterView.getRecordCicle().drawingCircleRadius;
messageView.setEnterTransitionInProgress(true);
recordCircle = chatActivityEnterView.getRecordCicle();
recordCircle.voiceEnterTransitionInProgress = true;
recordCircle.skipDraw = true;
gradientMatrix = new Matrix();
gradientPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
gradientPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
gradientShader = new LinearGradient(0, AndroidUtilities.dp(12), 0, 0, 0, 0xFF000000, Shader.TileMode.CLAMP);
gradientPaint.setShader(gradientShader);
messageId = messageView.getMessageObject().stableId;
container.addTransition(this);
animator = ValueAnimator.ofFloat(0f, 1f);
animator.addUpdateListener(valueAnimator -> {
progress = (float) valueAnimator.getAnimatedValue();
container.invalidate();
});
animator.setInterpolator(new LinearInterpolator());
animator.setDuration(220);
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
messageView.setEnterTransitionInProgress(false);
container.removeTransition(VoiceMessageEnterTransition.this);
recordCircle.skipDraw = false;
}
});
if (messageView.getSeekBarWaveform() != null) {
messageView.getSeekBarWaveform().setSent();
}
}
public void start() {
animator.start();
}
float lastToCx;
float lastToCy;
@Override
public void onDraw(Canvas canvas) {
float step1Time = 0.6f;
float moveProgress = progress;
float hideWavesProgress = progress > step1Time ? 1f : progress / step1Time;
float fromCx = recordCircle.drawingCx + recordCircle.getX() - container.getX();
float fromCy = recordCircle.drawingCy + recordCircle.getY() - container.getY();
float toCy;
float toCx;
if (messageView.getMessageObject().stableId != messageId) {
toCx = lastToCx;
toCy = lastToCy;
} else {
toCy = messageView.getRadialProgress().getProgressRect().centerY() + messageView.getY() + listView.getY() - container.getY();
toCx = messageView.getRadialProgress().getProgressRect().centerX() + messageView.getX() + listView.getX() - container.getX();
}
lastToCx = toCx;
lastToCy = toCy;
float progress = CubicBezierInterpolator.DEFAULT.getInterpolation(moveProgress);
float xProgress = CubicBezierInterpolator.EASE_OUT_QUINT.getInterpolation(moveProgress);
float cx = fromCx * (1f - xProgress) + toCx * xProgress;
float cy = fromCy * (1f - progress) + toCy * progress;
float toRadius = messageView.getRadialProgress().getProgressRect().height() / 2;
float radius = fromRadius * (1f - progress) + toRadius * progress;
float listViewBottom = listView.getY() - container.getY() + listView.getMeasuredHeight();
int clipBottom = 0;
if (container.getMeasuredHeight() > 0) {
clipBottom = (int) (container.getMeasuredHeight() * (1f - progress) + listViewBottom * progress);
canvas.saveLayerAlpha(0, container.getMeasuredHeight() - AndroidUtilities.dp(400), container.getMeasuredWidth(), container.getMeasuredHeight(), 255, Canvas.ALL_SAVE_FLAG);
} else {
canvas.save();
}
circlePaint.setColor(ColorUtils.blendARGB(getThemedColor(Theme.key_chat_messagePanelVoiceBackground), getThemedColor(messageView.getRadialProgress().getCircleColorKey()), progress));
recordCircle.drawWaves(canvas, cx, cy, 1f - hideWavesProgress);
canvas.drawCircle(cx, cy, radius, circlePaint);
canvas.save();
float scale = radius / toRadius;
canvas.scale(scale, scale, cx, cy);
canvas.translate(cx - messageView.getRadialProgress().getProgressRect().centerX(), cy - messageView.getRadialProgress().getProgressRect().centerY());
messageView.getRadialProgress().setOverrideAlpha(progress);
messageView.getRadialProgress().setDrawBackground(false);
messageView.getRadialProgress().draw(canvas);
messageView.getRadialProgress().setDrawBackground(true);
messageView.getRadialProgress().setOverrideAlpha(1f);
canvas.restore();
if (container.getMeasuredHeight() > 0) {
gradientMatrix.setTranslate(0, clipBottom);
gradientShader.setLocalMatrix(gradientMatrix);
canvas.drawRect(0, clipBottom, container.getMeasuredWidth(), container.getMeasuredHeight(), gradientPaint);
}
//restore clipRect
canvas.restore();
recordCircle.drawIcon(canvas, (int) fromCx, (int) fromCy, 1f - moveProgress);
}
private int getThemedColor(String key) {
Integer color = resourcesProvider != null ? resourcesProvider.getColor(key) : null;
return color != null ? color : Theme.getColor(key);
}
}