NekoX/TMessagesProj/src/main/java/org/telegram/ui/Components/ReplaceableIconDrawable.java

201 lines
5.4 KiB
Java

package org.telegram.ui.Components;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.widget.ImageView;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
public class ReplaceableIconDrawable extends Drawable implements Animator.AnimatorListener {
private Context context;
private ColorFilter colorFilter;
private int currentResId = 0;
private Drawable currentDrawable;
private Drawable outDrawable;
private ValueAnimator animation;
private float progress = 1f;
public ReplaceableIconDrawable(Context context) {
this.context = context;
}
public void setIcon(@DrawableRes int resId, boolean animated) {
if (currentResId == resId) {
return;
}
setIcon(ContextCompat.getDrawable(context, resId).mutate(), animated);
currentResId = resId;
}
public void setIcon(Drawable drawable, boolean animated) {
if (drawable == null) {
currentDrawable = null;
outDrawable = null;
invalidateSelf();
return;
}
if (getBounds() == null || getBounds().isEmpty()) {
animated = false;
}
if (drawable == currentDrawable) {
currentDrawable.setColorFilter(colorFilter);
return;
}
currentResId = 0;
outDrawable = currentDrawable;
currentDrawable = drawable;
currentDrawable.setColorFilter(colorFilter);
updateBounds(currentDrawable, getBounds());
updateBounds(outDrawable, getBounds());
if (animation != null) {
animation.removeAllListeners();
animation.cancel();
}
if (!animated) {
progress = 1f;
outDrawable = null;
return;
}
animation = ValueAnimator.ofFloat(0, 1f);
animation.addUpdateListener(animation -> {
progress = (float) animation.getAnimatedValue();
invalidateSelf();
});
animation.addListener(this);
animation.setDuration(150);
animation.start();
}
@Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
updateBounds(currentDrawable, bounds);
updateBounds(outDrawable, bounds);
}
private void updateBounds(Drawable d, Rect bounds) {
if (d == null) return;
int left;
int right;
int bottom;
int top;
if (d.getIntrinsicHeight() < 0) {
top = bounds.top;
bottom = bounds.bottom;
} else {
int offset = (bounds.height() - d.getIntrinsicHeight()) / 2;
top = bounds.top + offset;
bottom = bounds.top + offset + d.getIntrinsicHeight();
}
if (d.getIntrinsicWidth() < 0) {
left = bounds.left;
right = bounds.right;
} else {
int offset = (bounds.width() - d.getIntrinsicWidth()) / 2;
left = bounds.left + offset;
right = bounds.left + offset + d.getIntrinsicWidth();
}
d.setBounds(left, top, right, bottom);
}
@Override
public void draw(@NonNull Canvas canvas) {
int cX = getBounds().centerX();
int cY = getBounds().centerY();
if (progress != 1f && currentDrawable != null) {
canvas.save();
canvas.scale(progress, progress, cX, cY);
currentDrawable.setAlpha((int) (255 * progress));
currentDrawable.draw(canvas);
canvas.restore();
} else if (currentDrawable != null) {
currentDrawable.setAlpha(255);
currentDrawable.draw(canvas);
}
if (progress != 1f && outDrawable != null) {
float progressRev = 1f - progress;
canvas.save();
canvas.scale(progressRev, progressRev, cX, cY);
outDrawable.setAlpha((int) (255 * progressRev));
outDrawable.draw(canvas);
canvas.restore();
} else if (outDrawable != null) {
outDrawable.setAlpha(255);
outDrawable.draw(canvas);
}
}
@Override
public void setAlpha(int alpha) {
}
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {
this.colorFilter = colorFilter;
if (currentDrawable != null) {
currentDrawable.setColorFilter(colorFilter);
}
if (outDrawable != null) {
outDrawable.setColorFilter(colorFilter);
}
invalidateSelf();
}
@Override
public int getOpacity() {
return PixelFormat.TRANSPARENT;
}
@Override
public void onAnimationEnd(Animator animation) {
outDrawable = null;
invalidateSelf();
}
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
}