2015-10-29 18:10:07 +01:00
|
|
|
/*
|
2019-01-23 18:03:33 +01:00
|
|
|
* This is the source code of Telegram for Android v. 5.x.x.
|
2015-10-29 18:10:07 +01:00
|
|
|
* It is licensed under GNU GPL v. 2 or later.
|
|
|
|
* You should have received a copy of the license in this archive (see LICENSE).
|
|
|
|
*
|
2019-01-23 18:03:33 +01:00
|
|
|
* Copyright Nikolai Kudashov, 2013-2018.
|
2015-10-29 18:10:07 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
package org.telegram.ui.Components;
|
|
|
|
|
2016-06-24 12:27:15 +02:00
|
|
|
import android.animation.Animator;
|
2017-03-31 01:58:05 +02:00
|
|
|
import android.animation.AnimatorListenerAdapter;
|
2016-06-24 12:27:15 +02:00
|
|
|
import android.animation.ObjectAnimator;
|
2015-10-29 18:10:07 +01:00
|
|
|
import android.content.Context;
|
|
|
|
import android.graphics.Canvas;
|
|
|
|
import android.graphics.Paint;
|
|
|
|
import android.graphics.Typeface;
|
|
|
|
import android.text.Layout;
|
|
|
|
import android.text.StaticLayout;
|
|
|
|
import android.text.TextPaint;
|
|
|
|
import android.view.View;
|
2022-06-21 04:51:00 +02:00
|
|
|
import android.view.accessibility.AccessibilityNodeInfo;
|
2015-10-29 18:10:07 +01:00
|
|
|
|
|
|
|
import org.telegram.messenger.AndroidUtilities;
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Locale;
|
|
|
|
|
2020-03-30 14:00:09 +02:00
|
|
|
import androidx.annotation.Keep;
|
|
|
|
|
2015-10-29 18:10:07 +01:00
|
|
|
public class NumberTextView extends View {
|
|
|
|
|
|
|
|
private ArrayList<StaticLayout> letters = new ArrayList<>();
|
|
|
|
private ArrayList<StaticLayout> oldLetters = new ArrayList<>();
|
|
|
|
private TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
2016-06-24 12:27:15 +02:00
|
|
|
private ObjectAnimator animator;
|
2015-10-29 18:10:07 +01:00
|
|
|
private float progress = 0.0f;
|
|
|
|
private int currentNumber = 1;
|
2020-10-30 11:26:29 +01:00
|
|
|
private boolean addNumber;
|
2020-12-23 08:48:30 +01:00
|
|
|
private boolean center;
|
|
|
|
private float textWidth;
|
|
|
|
private float oldTextWidth;
|
2015-10-29 18:10:07 +01:00
|
|
|
|
2021-12-07 14:02:02 +01:00
|
|
|
private OnTextWidthProgressChangedListener onTextWidthProgressChangedListener;
|
|
|
|
|
2015-10-29 18:10:07 +01:00
|
|
|
public NumberTextView(Context context) {
|
|
|
|
super(context);
|
|
|
|
}
|
|
|
|
|
2021-12-07 14:02:02 +01:00
|
|
|
public void setOnTextWidthProgressChangedListener(OnTextWidthProgressChangedListener onTextWidthProgressChangedListener) {
|
|
|
|
this.onTextWidthProgressChangedListener = onTextWidthProgressChangedListener;
|
|
|
|
}
|
|
|
|
|
2020-03-30 14:00:09 +02:00
|
|
|
@Keep
|
2015-10-29 18:10:07 +01:00
|
|
|
public void setProgress(float value) {
|
|
|
|
if (progress == value) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
progress = value;
|
2021-12-07 14:02:02 +01:00
|
|
|
if (onTextWidthProgressChangedListener != null) {
|
|
|
|
onTextWidthProgressChangedListener.onTextWidthProgress(oldTextWidth, textWidth, progress);
|
|
|
|
}
|
2015-10-29 18:10:07 +01:00
|
|
|
invalidate();
|
|
|
|
}
|
|
|
|
|
2020-03-30 14:00:09 +02:00
|
|
|
@Keep
|
2015-10-29 18:10:07 +01:00
|
|
|
public float getProgress() {
|
|
|
|
return progress;
|
|
|
|
}
|
|
|
|
|
2020-10-30 11:26:29 +01:00
|
|
|
public void setAddNumber() {
|
|
|
|
addNumber = true;
|
|
|
|
}
|
|
|
|
|
2015-10-29 18:10:07 +01:00
|
|
|
public void setNumber(int number, boolean animated) {
|
|
|
|
if (currentNumber == number && animated) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (animator != null) {
|
|
|
|
animator.cancel();
|
|
|
|
animator = null;
|
|
|
|
}
|
|
|
|
oldLetters.clear();
|
|
|
|
oldLetters.addAll(letters);
|
|
|
|
letters.clear();
|
2020-10-30 11:26:29 +01:00
|
|
|
String oldText;
|
|
|
|
String text;
|
|
|
|
boolean forwardAnimation;
|
|
|
|
if (addNumber) {
|
|
|
|
oldText = String.format(Locale.US, "#%d", currentNumber);
|
|
|
|
text = String.format(Locale.US, "#%d", number);
|
|
|
|
forwardAnimation = number < currentNumber;
|
|
|
|
} else {
|
|
|
|
oldText = String.format(Locale.US, "%d", currentNumber);
|
|
|
|
text = String.format(Locale.US, "%d", number);
|
|
|
|
forwardAnimation = number > currentNumber;
|
|
|
|
}
|
2020-12-23 08:48:30 +01:00
|
|
|
boolean replace = false;
|
2021-12-07 14:02:02 +01:00
|
|
|
textWidth = textPaint.measureText(text);
|
|
|
|
oldTextWidth = textPaint.measureText(oldText);
|
2020-12-23 08:48:30 +01:00
|
|
|
if (center) {
|
|
|
|
if (textWidth != oldTextWidth) {
|
|
|
|
replace = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-29 18:10:07 +01:00
|
|
|
currentNumber = number;
|
|
|
|
progress = 0;
|
|
|
|
for (int a = 0; a < text.length(); a++) {
|
|
|
|
String ch = text.substring(a, a + 1);
|
|
|
|
String oldCh = !oldLetters.isEmpty() && a < oldText.length() ? oldText.substring(a, a + 1) : null;
|
2020-12-23 08:48:30 +01:00
|
|
|
if (!replace && oldCh != null && oldCh.equals(ch)) {
|
2015-10-29 18:10:07 +01:00
|
|
|
letters.add(oldLetters.get(a));
|
|
|
|
oldLetters.set(a, null);
|
|
|
|
} else {
|
2020-12-23 08:48:30 +01:00
|
|
|
if (replace && oldCh == null) {
|
|
|
|
oldLetters.add(new StaticLayout("", textPaint, 0, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false));
|
|
|
|
}
|
2015-10-29 18:10:07 +01:00
|
|
|
StaticLayout layout = new StaticLayout(ch, textPaint, (int) Math.ceil(textPaint.measureText(ch)), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
|
|
|
|
letters.add(layout);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (animated && !oldLetters.isEmpty()) {
|
2016-06-24 12:27:15 +02:00
|
|
|
animator = ObjectAnimator.ofFloat(this, "progress", forwardAnimation ? -1 : 1, 0);
|
2020-10-30 11:26:29 +01:00
|
|
|
animator.setDuration(addNumber ? 180 : 150);
|
2017-03-31 01:58:05 +02:00
|
|
|
animator.addListener(new AnimatorListenerAdapter() {
|
2015-10-29 18:10:07 +01:00
|
|
|
@Override
|
2016-06-24 12:27:15 +02:00
|
|
|
public void onAnimationEnd(Animator animation) {
|
2015-10-29 18:10:07 +01:00
|
|
|
animator = null;
|
|
|
|
oldLetters.clear();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
animator.start();
|
2021-12-07 14:02:02 +01:00
|
|
|
} else if (onTextWidthProgressChangedListener != null) {
|
|
|
|
onTextWidthProgressChangedListener.onTextWidthProgress(oldTextWidth, textWidth, progress);
|
2015-10-29 18:10:07 +01:00
|
|
|
}
|
|
|
|
invalidate();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setTextSize(int size) {
|
|
|
|
textPaint.setTextSize(AndroidUtilities.dp(size));
|
|
|
|
oldLetters.clear();
|
|
|
|
letters.clear();
|
|
|
|
setNumber(currentNumber, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setTextColor(int value) {
|
|
|
|
textPaint.setColor(value);
|
|
|
|
invalidate();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setTypeface(Typeface typeface) {
|
|
|
|
textPaint.setTypeface(typeface);
|
|
|
|
oldLetters.clear();
|
|
|
|
letters.clear();
|
|
|
|
setNumber(currentNumber, false);
|
|
|
|
}
|
|
|
|
|
2020-12-23 08:48:30 +01:00
|
|
|
public void setCenterAlign(boolean center) {
|
|
|
|
this.center = center;
|
|
|
|
}
|
|
|
|
|
2015-10-29 18:10:07 +01:00
|
|
|
@Override
|
|
|
|
protected void onDraw(Canvas canvas) {
|
|
|
|
if (letters.isEmpty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
float height = letters.get(0).getHeight();
|
2020-10-30 11:26:29 +01:00
|
|
|
float translationHeight = addNumber ? AndroidUtilities.dp(4) : height;
|
2020-12-23 08:48:30 +01:00
|
|
|
|
|
|
|
float x = 0;
|
|
|
|
float oldDx = 0;
|
|
|
|
if (center) {
|
|
|
|
x = (getMeasuredWidth() - textWidth) / 2f;
|
|
|
|
oldDx = (getMeasuredWidth() - oldTextWidth) / 2f - x;
|
|
|
|
}
|
2015-10-29 18:10:07 +01:00
|
|
|
canvas.save();
|
2020-12-23 08:48:30 +01:00
|
|
|
canvas.translate(getPaddingLeft() + x, (getMeasuredHeight() - height) / 2);
|
2015-10-29 18:10:07 +01:00
|
|
|
int count = Math.max(letters.size(), oldLetters.size());
|
|
|
|
for (int a = 0; a < count; a++) {
|
|
|
|
canvas.save();
|
|
|
|
StaticLayout old = a < oldLetters.size() ? oldLetters.get(a) : null;
|
|
|
|
StaticLayout layout = a < letters.size() ? letters.get(a) : null;
|
|
|
|
if (progress > 0) {
|
|
|
|
if (old != null) {
|
|
|
|
textPaint.setAlpha((int) (255 * progress));
|
|
|
|
canvas.save();
|
2020-12-23 08:48:30 +01:00
|
|
|
canvas.translate(oldDx, (progress - 1.0f) * translationHeight);
|
2015-10-29 18:10:07 +01:00
|
|
|
old.draw(canvas);
|
|
|
|
canvas.restore();
|
|
|
|
if (layout != null) {
|
|
|
|
textPaint.setAlpha((int) (255 * (1.0f - progress)));
|
2020-10-30 11:26:29 +01:00
|
|
|
canvas.translate(0, progress * translationHeight);
|
2015-10-29 18:10:07 +01:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
textPaint.setAlpha(255);
|
|
|
|
}
|
|
|
|
} else if (progress < 0) {
|
|
|
|
if (old != null) {
|
|
|
|
textPaint.setAlpha((int) (255 * -progress));
|
|
|
|
canvas.save();
|
2020-12-23 08:48:30 +01:00
|
|
|
canvas.translate(oldDx, (1.0f + progress) * translationHeight);
|
2015-10-29 18:10:07 +01:00
|
|
|
old.draw(canvas);
|
|
|
|
canvas.restore();
|
|
|
|
}
|
|
|
|
if (layout != null) {
|
|
|
|
if (a == count - 1 || old != null) {
|
|
|
|
textPaint.setAlpha((int) (255 * (1.0f + progress)));
|
2020-10-30 11:26:29 +01:00
|
|
|
canvas.translate(0, progress * translationHeight);
|
2015-10-29 18:10:07 +01:00
|
|
|
} else {
|
|
|
|
textPaint.setAlpha(255);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (layout != null) {
|
|
|
|
textPaint.setAlpha(255);
|
|
|
|
}
|
|
|
|
if (layout != null) {
|
|
|
|
layout.draw(canvas);
|
|
|
|
}
|
|
|
|
canvas.restore();
|
|
|
|
canvas.translate(layout != null ? layout.getLineWidth(0) : old.getLineWidth(0) + AndroidUtilities.dp(1), 0);
|
2020-12-23 08:48:30 +01:00
|
|
|
if (layout != null && old != null) {
|
|
|
|
oldDx += old.getLineWidth(0) - layout.getLineWidth(0);
|
|
|
|
}
|
2015-10-29 18:10:07 +01:00
|
|
|
}
|
|
|
|
canvas.restore();
|
|
|
|
}
|
2021-12-07 14:02:02 +01:00
|
|
|
|
|
|
|
public float getOldTextWidth() {
|
|
|
|
return oldTextWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
public float getTextWidth() {
|
|
|
|
return textWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
public interface OnTextWidthProgressChangedListener {
|
|
|
|
/**
|
|
|
|
* Notifies layout that text width has changed
|
|
|
|
* @param fromWidth Old text width value
|
|
|
|
* @param toWidth New text width value
|
|
|
|
* @param progress Progress for the animation
|
|
|
|
*/
|
|
|
|
void onTextWidthProgress(float fromWidth, float toWidth, float progress);
|
|
|
|
}
|
2015-10-29 18:10:07 +01:00
|
|
|
}
|