mirror of https://github.com/NekoX-Dev/NekoX.git
387 lines
15 KiB
Java
387 lines
15 KiB
Java
package org.telegram.ui;
|
|
|
|
import android.animation.Animator;
|
|
import android.animation.AnimatorListenerAdapter;
|
|
import android.animation.ValueAnimator;
|
|
import android.content.Context;
|
|
import android.graphics.Canvas;
|
|
import android.graphics.Color;
|
|
import android.graphics.Paint;
|
|
import android.graphics.Path;
|
|
import android.graphics.Rect;
|
|
import android.graphics.RectF;
|
|
import android.graphics.Typeface;
|
|
import android.graphics.drawable.GradientDrawable;
|
|
import android.os.Build;
|
|
import android.os.SystemClock;
|
|
import android.text.TextPaint;
|
|
import android.view.View;
|
|
|
|
import org.telegram.messenger.AndroidUtilities;
|
|
import org.telegram.ui.ActionBar.ActionBar;
|
|
import org.telegram.ui.Components.CubicBezierInterpolator;
|
|
import org.telegram.ui.Components.ProfileGalleryView;
|
|
|
|
import java.util.Arrays;
|
|
|
|
public class AvatarPreviewPagerIndicator extends View implements ProfileGalleryView.Callback {
|
|
|
|
private final RectF indicatorRect = new RectF();
|
|
|
|
private final int statusBarHeight = 0;
|
|
private int overlayCountVisible = 1;
|
|
|
|
private final Rect topOverlayRect = new Rect();
|
|
private final Rect bottomOverlayRect = new Rect();
|
|
private final RectF rect = new RectF();
|
|
|
|
private final GradientDrawable topOverlayGradient;
|
|
private final GradientDrawable bottomOverlayGradient;
|
|
private final ValueAnimator animator;
|
|
private final float[] animatorValues = new float[]{0f, 1f};
|
|
private final Paint backgroundPaint;
|
|
private final Paint barPaint;
|
|
private final Paint selectedBarPaint;
|
|
|
|
Path path = new Path();
|
|
RectF rectF = new RectF();
|
|
|
|
private final GradientDrawable[] pressedOverlayGradient = new GradientDrawable[2];
|
|
private final boolean[] pressedOverlayVisible = new boolean[2];
|
|
private final float[] pressedOverlayAlpha = new float[2];
|
|
|
|
private boolean isOverlaysVisible;
|
|
private float currentAnimationValue;
|
|
private float alpha = 0f;
|
|
private float[] alphas = null;
|
|
private long lastTime;
|
|
private float previousSelectedProgress;
|
|
private int previousSelectedPotision = -1;
|
|
private float currentProgress;
|
|
private int selectedPosition;
|
|
|
|
private float currentLoadingAnimationProgress;
|
|
private int currentLoadingAnimationDirection = 1;
|
|
|
|
protected ProfileGalleryView profileGalleryView;
|
|
|
|
TextPaint textPaint;
|
|
private float progressToCounter;
|
|
|
|
public AvatarPreviewPagerIndicator(Context context) {
|
|
super(context);
|
|
|
|
barPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
barPaint.setColor(0x55ffffff);
|
|
selectedBarPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
selectedBarPaint.setColor(0xffffffff);
|
|
|
|
topOverlayGradient = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, new int[] {0x42000000, 0});
|
|
topOverlayGradient.setShape(GradientDrawable.RECTANGLE);
|
|
|
|
bottomOverlayGradient = new GradientDrawable(GradientDrawable.Orientation.BOTTOM_TOP, new int[] {0x42000000, 0});
|
|
bottomOverlayGradient.setShape(GradientDrawable.RECTANGLE);
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
final GradientDrawable.Orientation orientation = i == 0 ? GradientDrawable.Orientation.LEFT_RIGHT : GradientDrawable.Orientation.RIGHT_LEFT;
|
|
pressedOverlayGradient[i] = new GradientDrawable(orientation, new int[] {0x32000000, 0});
|
|
pressedOverlayGradient[i].setShape(GradientDrawable.RECTANGLE);
|
|
}
|
|
|
|
backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
backgroundPaint.setColor(Color.BLACK);
|
|
backgroundPaint.setAlpha(66);
|
|
animator = ValueAnimator.ofFloat(0f, 1f);
|
|
animator.setDuration(250);
|
|
animator.setInterpolator(CubicBezierInterpolator.EASE_BOTH);
|
|
animator.addUpdateListener(anim -> {
|
|
float value = AndroidUtilities.lerp(animatorValues, currentAnimationValue = anim.getAnimatedFraction());
|
|
setAlphaValue(value, true);
|
|
});
|
|
animator.addListener(new AnimatorListenerAdapter() {
|
|
@Override
|
|
public void onAnimationEnd(Animator animation) {
|
|
if (!isOverlaysVisible) {
|
|
setVisibility(GONE);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onAnimationStart(Animator animation) {
|
|
setVisibility(VISIBLE);
|
|
}
|
|
});
|
|
|
|
|
|
textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
|
textPaint.setColor(Color.WHITE);
|
|
textPaint.setTypeface(Typeface.SANS_SERIF);
|
|
textPaint.setTextAlign(Paint.Align.CENTER);
|
|
textPaint.setTextSize(AndroidUtilities.dpf2(15f));
|
|
}
|
|
|
|
public void saveCurrentPageProgress() {
|
|
previousSelectedProgress = currentProgress;
|
|
previousSelectedPotision = selectedPosition;
|
|
currentLoadingAnimationProgress = 0.0f;
|
|
currentLoadingAnimationDirection = 1;
|
|
}
|
|
|
|
public void setAlphaValue(float value, boolean self) {
|
|
if (Build.VERSION.SDK_INT > 18) {
|
|
int alpha = (int) (255 * value);
|
|
topOverlayGradient.setAlpha(alpha);
|
|
bottomOverlayGradient.setAlpha(alpha);
|
|
backgroundPaint.setAlpha((int) (66 * value));
|
|
barPaint.setAlpha((int) (0x55 * value));
|
|
selectedBarPaint.setAlpha(alpha);
|
|
this.alpha = value;
|
|
} else {
|
|
setAlpha(value);
|
|
}
|
|
if (!self) {
|
|
currentAnimationValue = value;
|
|
}
|
|
invalidate();
|
|
}
|
|
|
|
@Override
|
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
|
path.reset();
|
|
rectF.set(0, 0, getMeasuredHeight(), getMeasuredWidth());
|
|
path.addRoundRect(rectF, new float[]{AndroidUtilities.dp(13), AndroidUtilities.dp(13), AndroidUtilities.dp(13), AndroidUtilities.dp(13), 0, 0, 0, 0}, Path.Direction.CCW);
|
|
}
|
|
|
|
@Override
|
|
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
|
final int actionBarHeight = statusBarHeight + ActionBar.getCurrentActionBarHeight();
|
|
final float k = 0.5f;
|
|
topOverlayRect.set(0, 0, w, (int) (actionBarHeight * k));
|
|
bottomOverlayRect.set(0, (int) (h - AndroidUtilities.dp(72f) * k), w, h);
|
|
topOverlayGradient.setBounds(0, topOverlayRect.bottom, w, actionBarHeight + AndroidUtilities.dp(16f));
|
|
bottomOverlayGradient.setBounds(0, h - AndroidUtilities.dp(72f) - AndroidUtilities.dp(24f), w, bottomOverlayRect.top);
|
|
pressedOverlayGradient[0].setBounds(0, 0, w / 5, h);
|
|
pressedOverlayGradient[1].setBounds(w - (w / 5), 0, w, h);
|
|
}
|
|
|
|
@Override
|
|
protected void onDraw(Canvas canvas) {
|
|
// canvas.save();
|
|
// canvas.clipPath(path);
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
if (pressedOverlayAlpha[i] > 0f) {
|
|
pressedOverlayGradient[i].setAlpha((int) (pressedOverlayAlpha[i] * 255));
|
|
pressedOverlayGradient[i].draw(canvas);
|
|
}
|
|
}
|
|
|
|
topOverlayGradient.draw(canvas);
|
|
canvas.drawRect(topOverlayRect, backgroundPaint);
|
|
//canvas.restore();
|
|
|
|
|
|
int count = profileGalleryView.getRealCount();
|
|
selectedPosition = profileGalleryView.getRealPosition();
|
|
|
|
if (alphas == null || alphas.length != count) {
|
|
alphas = new float[count];
|
|
Arrays.fill(alphas, 0.0f);
|
|
}
|
|
|
|
boolean invalidate = false;
|
|
|
|
long newTime = SystemClock.elapsedRealtime();
|
|
long dt = (newTime - lastTime);
|
|
if (dt < 0 || dt > 20) {
|
|
dt = 17;
|
|
}
|
|
lastTime = newTime;
|
|
|
|
if (count > 1 && count <= 20) {
|
|
if (overlayCountVisible == 0) {
|
|
alpha = 0.0f;
|
|
overlayCountVisible = 3;
|
|
} else if (overlayCountVisible == 1) {
|
|
alpha = 0.0f;
|
|
overlayCountVisible = 2;
|
|
}
|
|
if (overlayCountVisible == 2) {
|
|
barPaint.setAlpha((int) (0x55 * alpha));
|
|
selectedBarPaint.setAlpha((int) (0xff * alpha));
|
|
}
|
|
int width = (getMeasuredWidth() - AndroidUtilities.dp(5 * 2) - AndroidUtilities.dp(2 * (count - 1))) / count;
|
|
int y = AndroidUtilities.dp(8);
|
|
for (int a = 0; a < count; a++) {
|
|
int x = AndroidUtilities.dp(5 + a * 2) + width * a;
|
|
float progress;
|
|
int baseAlpha = 0x55;
|
|
if (a == previousSelectedPotision && Math.abs(previousSelectedProgress - 1.0f) > 0.0001f) {
|
|
progress = previousSelectedProgress;
|
|
canvas.save();
|
|
canvas.clipRect(x + width * progress, y, x + width, y + AndroidUtilities.dp(2));
|
|
rect.set(x, y, x + width, y + AndroidUtilities.dp(2));
|
|
barPaint.setAlpha((int) (0x55 * alpha));
|
|
canvas.drawRoundRect(rect, AndroidUtilities.dp(1), AndroidUtilities.dp(1), barPaint);
|
|
baseAlpha = 0x50;
|
|
canvas.restore();
|
|
invalidate = true;
|
|
} else if (a == selectedPosition) {
|
|
if (profileGalleryView.isCurrentItemVideo()) {
|
|
progress = currentProgress = profileGalleryView.getCurrentItemProgress();
|
|
if (progress <= 0 && profileGalleryView.isLoadingCurrentVideo() || currentLoadingAnimationProgress > 0.0f) {
|
|
currentLoadingAnimationProgress += currentLoadingAnimationDirection * dt / 500.0f;
|
|
if (currentLoadingAnimationProgress > 1.0f) {
|
|
currentLoadingAnimationProgress = 1.0f;
|
|
currentLoadingAnimationDirection *= -1;
|
|
} else if (currentLoadingAnimationProgress <= 0) {
|
|
currentLoadingAnimationProgress = 0.0f;
|
|
currentLoadingAnimationDirection *= -1;
|
|
}
|
|
}
|
|
rect.set(x, y, x + width, y + AndroidUtilities.dp(2));
|
|
barPaint.setAlpha((int) ((0x55 + 0x30 * currentLoadingAnimationProgress) * alpha));
|
|
canvas.drawRoundRect(rect, AndroidUtilities.dp(1), AndroidUtilities.dp(1), barPaint);
|
|
invalidate = true;
|
|
baseAlpha = 0x50;
|
|
} else {
|
|
progress = currentProgress = 1.0f;
|
|
}
|
|
} else {
|
|
progress = 1.0f;
|
|
}
|
|
rect.set(x, y, x + width * progress, y + AndroidUtilities.dp(2));
|
|
|
|
if (a != selectedPosition) {
|
|
if (overlayCountVisible == 3) {
|
|
barPaint.setAlpha((int) (AndroidUtilities.lerp(baseAlpha, 0xff, CubicBezierInterpolator.EASE_BOTH.getInterpolation(alphas[a])) * alpha));
|
|
}
|
|
} else {
|
|
alphas[a] = 0.75f;
|
|
}
|
|
canvas.drawRoundRect(rect, AndroidUtilities.dp(1), AndroidUtilities.dp(1), a == selectedPosition ? selectedBarPaint : barPaint);
|
|
}
|
|
|
|
if (overlayCountVisible == 2) {
|
|
if (alpha < 1.0f) {
|
|
alpha += dt / 180.0f;
|
|
if (alpha > 1.0f) {
|
|
alpha = 1.0f;
|
|
}
|
|
invalidate = true;
|
|
} else {
|
|
overlayCountVisible = 3;
|
|
}
|
|
} else if (overlayCountVisible == 3) {
|
|
for (int i = 0; i < alphas.length; i++) {
|
|
if (i != selectedPosition && alphas[i] > 0.0f) {
|
|
alphas[i] -= dt / 500.0f;
|
|
if (alphas[i] <= 0.0f) {
|
|
alphas[i] = 0.0f;
|
|
if (i == previousSelectedPotision) {
|
|
previousSelectedPotision = -1;
|
|
}
|
|
}
|
|
invalidate = true;
|
|
} else if (i == previousSelectedPotision) {
|
|
previousSelectedPotision = -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (count > 20 || progressToCounter != 0) {
|
|
final float textWidth = textPaint.measureText(getCurrentTitle());
|
|
indicatorRect.right = getMeasuredWidth() - AndroidUtilities.dp(8f);
|
|
indicatorRect.left = indicatorRect.right - (textWidth + AndroidUtilities.dpf2(16f));
|
|
indicatorRect.top = AndroidUtilities.dp(8f);
|
|
indicatorRect.bottom = indicatorRect.top + AndroidUtilities.dp(26);
|
|
|
|
final float radius = AndroidUtilities.dpf2(12);
|
|
canvas.save();
|
|
boolean showCounter = count > 20;
|
|
if (showCounter && progressToCounter != 1f) {
|
|
progressToCounter += dt / 150f;
|
|
} else if (!showCounter && progressToCounter != 0f) {
|
|
progressToCounter -= dt / 150f;
|
|
}
|
|
if (progressToCounter >= 1f) {
|
|
progressToCounter = 1f;
|
|
} else if (progressToCounter <= 0) {
|
|
progressToCounter = 0f;
|
|
} else {
|
|
invalidate();
|
|
}
|
|
canvas.scale(progressToCounter, progressToCounter, indicatorRect.centerX(), indicatorRect.centerY());
|
|
canvas.drawRoundRect(indicatorRect, radius, radius, backgroundPaint);
|
|
canvas.drawText(getCurrentTitle(), indicatorRect.centerX(), indicatorRect.top + AndroidUtilities.dpf2(18.5f), textPaint);
|
|
canvas.restore();
|
|
}
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
if (pressedOverlayVisible[i]) {
|
|
if (pressedOverlayAlpha[i] < 1f) {
|
|
pressedOverlayAlpha[i] += dt / 180.0f;
|
|
if (pressedOverlayAlpha[i] > 1f) {
|
|
pressedOverlayAlpha[i] = 1f;
|
|
}
|
|
invalidate = true;
|
|
}
|
|
} else {
|
|
if (pressedOverlayAlpha[i] > 0f) {
|
|
pressedOverlayAlpha[i] -= dt / 180.0f;
|
|
if (pressedOverlayAlpha[i] < 0f) {
|
|
pressedOverlayAlpha[i] = 0f;
|
|
}
|
|
invalidate = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (invalidate) {
|
|
postInvalidateOnAnimation();
|
|
}
|
|
}
|
|
|
|
int lastCurrentItem = -1;
|
|
String title;
|
|
|
|
private String getCurrentTitle() {
|
|
if (lastCurrentItem != profileGalleryView.getCurrentItem()) {
|
|
title = profileGalleryView.getAdapter().getPageTitle(profileGalleryView.getCurrentItem()).toString();
|
|
lastCurrentItem = profileGalleryView.getCurrentItem();
|
|
}
|
|
return title;
|
|
}
|
|
|
|
public void onDown(boolean left) {
|
|
pressedOverlayVisible[left ? 0 : 1] = true;
|
|
postInvalidateOnAnimation();
|
|
}
|
|
|
|
public void onRelease() {
|
|
Arrays.fill(pressedOverlayVisible, false);
|
|
postInvalidateOnAnimation();
|
|
}
|
|
|
|
@Override
|
|
public void onClick() {
|
|
}
|
|
|
|
@Override
|
|
public void onPhotosLoaded() {
|
|
}
|
|
|
|
@Override
|
|
public void onVideoSet() {
|
|
invalidate();
|
|
}
|
|
|
|
public void setProfileGalleryView(ProfileGalleryView profileGalleryView) {
|
|
this.profileGalleryView = profileGalleryView;
|
|
}
|
|
|
|
public ProfileGalleryView getProfileGalleryView() {
|
|
return profileGalleryView;
|
|
}
|
|
} |