mirror of https://github.com/NekoX-Dev/NekoX.git
226 lines
7.8 KiB
Java
226 lines
7.8 KiB
Java
/*
|
|
* This is the source code of Telegram for Android v. 5.x.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.animation.AnimatorSet;
|
|
import android.animation.ObjectAnimator;
|
|
import android.content.Context;
|
|
import android.graphics.Canvas;
|
|
import android.graphics.Paint;
|
|
import android.graphics.drawable.Drawable;
|
|
import android.os.Build;
|
|
import android.view.MotionEvent;
|
|
import android.view.View;
|
|
import android.view.ViewConfiguration;
|
|
import android.view.accessibility.AccessibilityNodeInfo;
|
|
import android.view.animation.DecelerateInterpolator;
|
|
|
|
import org.telegram.messenger.AndroidUtilities;
|
|
import org.telegram.messenger.LocaleController;
|
|
import org.telegram.messenger.R;
|
|
|
|
import androidx.annotation.Keep;
|
|
|
|
public class ShutterButton extends View {
|
|
|
|
public enum State {
|
|
DEFAULT,
|
|
RECORDING
|
|
}
|
|
|
|
private final static int LONG_PRESS_TIME = 800;
|
|
|
|
private Drawable shadowDrawable;
|
|
|
|
private DecelerateInterpolator interpolator = new DecelerateInterpolator();
|
|
private Paint whitePaint;
|
|
private Paint redPaint;
|
|
private ShutterButtonDelegate delegate;
|
|
private State state;
|
|
private boolean pressed;
|
|
private float redProgress;
|
|
private long lastUpdateTime;
|
|
private long totalTime;
|
|
private boolean processRelease;
|
|
|
|
private Runnable longPressed = new Runnable() {
|
|
public void run() {
|
|
if (delegate != null) {
|
|
if (!delegate.shutterLongPressed()) {
|
|
processRelease = false;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
public interface ShutterButtonDelegate {
|
|
boolean shutterLongPressed();
|
|
void shutterReleased();
|
|
void shutterCancel();
|
|
boolean onTranslationChanged(float x, float y);
|
|
}
|
|
|
|
public ShutterButton(Context context) {
|
|
super(context);
|
|
shadowDrawable = getResources().getDrawable(R.drawable.camera_btn);
|
|
whitePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
whitePaint.setStyle(Paint.Style.FILL);
|
|
whitePaint.setColor(0xffffffff);
|
|
redPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
redPaint.setStyle(Paint.Style.FILL);
|
|
redPaint.setColor(0xffcd4747);
|
|
state = State.DEFAULT;
|
|
}
|
|
|
|
public void setDelegate(ShutterButtonDelegate shutterButtonDelegate) {
|
|
delegate = shutterButtonDelegate;
|
|
}
|
|
|
|
public ShutterButtonDelegate getDelegate() {
|
|
return delegate;
|
|
}
|
|
|
|
private void setHighlighted(boolean value) {
|
|
AnimatorSet animatorSet = new AnimatorSet();
|
|
if (value) {
|
|
animatorSet.playTogether(
|
|
ObjectAnimator.ofFloat(this, View.SCALE_X, 1.06f),
|
|
ObjectAnimator.ofFloat(this, View.SCALE_Y, 1.06f));
|
|
} else {
|
|
animatorSet.playTogether(
|
|
ObjectAnimator.ofFloat(this, View.SCALE_X, 1.0f),
|
|
ObjectAnimator.ofFloat(this, View.SCALE_Y, 1.0f));
|
|
animatorSet.setStartDelay(40);
|
|
}
|
|
animatorSet.setDuration(120);
|
|
animatorSet.setInterpolator(interpolator);
|
|
animatorSet.start();
|
|
}
|
|
|
|
@Keep
|
|
@Override
|
|
public void setScaleX(float scaleX) {
|
|
super.setScaleX(scaleX);
|
|
invalidate();
|
|
}
|
|
|
|
public State getState() {
|
|
return state;
|
|
}
|
|
|
|
@Override
|
|
protected void onDraw(Canvas canvas) {
|
|
int cx = getMeasuredWidth() / 2;
|
|
int cy = getMeasuredHeight() / 2;
|
|
|
|
shadowDrawable.setBounds(cx - AndroidUtilities.dp(36), cy - AndroidUtilities.dp(36), cx + AndroidUtilities.dp(36), cy + AndroidUtilities.dp(36));
|
|
shadowDrawable.draw(canvas);
|
|
if (pressed || getScaleX() != 1.0f) {
|
|
float scale = (getScaleX() - 1.0f) / 0.06f;
|
|
whitePaint.setAlpha((int) (255 * scale));
|
|
canvas.drawCircle(cx, cy, AndroidUtilities.dp(26), whitePaint);
|
|
|
|
if (state == State.RECORDING) {
|
|
if (redProgress != 1.0f) {
|
|
long dt = Math.abs(System.currentTimeMillis() - lastUpdateTime);
|
|
if (dt > 17) {
|
|
dt = 17;
|
|
}
|
|
totalTime += dt;
|
|
if (totalTime > 120) {
|
|
totalTime = 120;
|
|
}
|
|
redProgress = interpolator.getInterpolation(totalTime / 120.0f);
|
|
invalidate();
|
|
}
|
|
canvas.drawCircle(cx, cy, AndroidUtilities.dp(26.5f) * scale * redProgress, redPaint);
|
|
} else if (redProgress != 0) {
|
|
canvas.drawCircle(cx, cy, AndroidUtilities.dp(26.5f) * scale, redPaint);
|
|
}
|
|
} else if (redProgress != 0) {
|
|
redProgress = 0;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
|
setMeasuredDimension(AndroidUtilities.dp(84), AndroidUtilities.dp(84));
|
|
}
|
|
|
|
@Override
|
|
public boolean onTouchEvent(MotionEvent motionEvent) {
|
|
float x = motionEvent.getX();
|
|
float y = motionEvent.getY();
|
|
switch (motionEvent.getAction()) {
|
|
case MotionEvent.ACTION_DOWN:
|
|
AndroidUtilities.runOnUIThread(longPressed, LONG_PRESS_TIME);
|
|
pressed = true;
|
|
processRelease = true;
|
|
setHighlighted(true);
|
|
break;
|
|
case MotionEvent.ACTION_UP:
|
|
setHighlighted(false);
|
|
AndroidUtilities.cancelRunOnUIThread(longPressed);
|
|
if (processRelease) {
|
|
delegate.shutterReleased();
|
|
}
|
|
break;
|
|
case MotionEvent.ACTION_MOVE:
|
|
float dx = x >= 0 && x <= getMeasuredWidth() ? 0 : x;
|
|
float dy = y >= 0 && y <= getMeasuredHeight() ? 0 : y;
|
|
if (delegate.onTranslationChanged(dx, dy)) {
|
|
AndroidUtilities.cancelRunOnUIThread(longPressed);
|
|
if (state == State.RECORDING) {
|
|
processRelease = false;
|
|
setHighlighted(false);
|
|
delegate.shutterCancel();
|
|
setState(State.DEFAULT, true);
|
|
}
|
|
}
|
|
break;
|
|
case MotionEvent.ACTION_CANCEL:
|
|
setHighlighted(false);
|
|
pressed = false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public void setState(State value, boolean animated) {
|
|
if (state != value) {
|
|
state = value;
|
|
if (animated) {
|
|
lastUpdateTime = System.currentTimeMillis();
|
|
totalTime = 0;
|
|
if (state != State.RECORDING) {
|
|
redProgress = 0.0f;
|
|
}
|
|
} else {
|
|
if (state == State.RECORDING) {
|
|
redProgress = 1.0f;
|
|
} else {
|
|
redProgress = 0.0f;
|
|
}
|
|
}
|
|
invalidate();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
|
|
super.onInitializeAccessibilityNodeInfo(info);
|
|
info.setClassName("android.widget.Button");
|
|
info.setClickable(true);
|
|
info.setLongClickable(true);
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
info.addAction(new AccessibilityNodeInfo.AccessibilityAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK.getId(), LocaleController.getString("AccActionTakePicture", R.string.AccActionTakePicture)));
|
|
info.addAction(new AccessibilityNodeInfo.AccessibilityAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK.getId(), LocaleController.getString("AccActionRecordVideo", R.string.AccActionRecordVideo)));
|
|
}
|
|
}
|
|
}
|