barinsta/app/src/main/java/awais/instagrabber/customviews/drawee/AbstractAnimatedZoomableCon...

171 lines
6.0 KiB
Java

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package awais.instagrabber.customviews.drawee;
import android.graphics.Matrix;
import android.graphics.PointF;
import androidx.annotation.Nullable;
import com.facebook.common.logging.FLog;
/**
* Abstract class for ZoomableController that adds animation capabilities to
* DefaultZoomableController.
*/
public abstract class AbstractAnimatedZoomableController extends DefaultZoomableController {
private boolean mIsAnimating;
private final float[] mStartValues = new float[9];
private final float[] mStopValues = new float[9];
private final float[] mCurrentValues = new float[9];
private final Matrix mNewTransform = new Matrix();
private final Matrix mWorkingTransform = new Matrix();
public AbstractAnimatedZoomableController(TransformGestureDetector transformGestureDetector) {
super(transformGestureDetector);
}
@Override
public void reset() {
FLog.v(getLogTag(), "reset");
stopAnimation();
mWorkingTransform.reset();
mNewTransform.reset();
super.reset();
}
/**
* Returns true if the zoomable transform is identity matrix, and the controller is idle.
*/
@Override
public boolean isIdentity() {
return !isAnimating() && super.isIdentity();
}
/**
* Zooms to the desired scale and positions the image so that the given image point corresponds to
* the given view point.
*
* <p>If this method is called while an animation or gesture is already in progress, the current
* animation or gesture will be stopped first.
*
* @param scale desired scale, will be limited to {min, max} scale factor
* @param imagePoint 2D point in image's relative coordinate system (i.e. 0 <= x, y <= 1)
* @param viewPoint 2D point in view's absolute coordinate system
*/
@Override
public void zoomToPoint(float scale, PointF imagePoint, PointF viewPoint) {
zoomToPoint(scale, imagePoint, viewPoint, LIMIT_ALL, 0, null);
}
/**
* Zooms to the desired scale and positions the image so that the given image point corresponds to
* the given view point.
*
* <p>If this method is called while an animation or gesture is already in progress, the current
* animation or gesture will be stopped first.
*
* @param scale desired scale, will be limited to {min, max} scale factor
* @param imagePoint 2D point in image's relative coordinate system (i.e. 0 <= x, y <= 1)
* @param viewPoint 2D point in view's absolute coordinate system
* @param limitFlags whether to limit translation and/or scale.
* @param durationMs length of animation of the zoom, or 0 if no animation desired
* @param onAnimationComplete code to run when the animation completes. Ignored if durationMs=0
*/
public void zoomToPoint(
float scale,
PointF imagePoint,
PointF viewPoint,
@LimitFlag int limitFlags,
long durationMs,
@Nullable Runnable onAnimationComplete) {
FLog.v(getLogTag(), "zoomToPoint: duration %d ms", durationMs);
calculateZoomToPointTransform(mNewTransform, scale, imagePoint, viewPoint, limitFlags);
setTransform(mNewTransform, durationMs, onAnimationComplete);
}
/**
* Sets a new zoomable transformation and animates to it if desired.
*
* <p>If this method is called while an animation or gesture is already in progress, the current
* animation or gesture will be stopped first.
*
* @param newTransform new transform to make active
* @param durationMs duration of the animation, or 0 to not animate
* @param onAnimationComplete code to run when the animation completes. Ignored if durationMs=0
*/
public void setTransform(
Matrix newTransform, long durationMs, @Nullable Runnable onAnimationComplete) {
FLog.v(getLogTag(), "setTransform: duration %d ms", durationMs);
if (durationMs <= 0) {
setTransformImmediate(newTransform);
} else {
setTransformAnimated(newTransform, durationMs, onAnimationComplete);
}
}
private void setTransformImmediate(final Matrix newTransform) {
FLog.v(getLogTag(), "setTransformImmediate");
stopAnimation();
mWorkingTransform.set(newTransform);
super.setTransform(newTransform);
getDetector().restartGesture();
}
protected boolean isAnimating() {
return mIsAnimating;
}
protected void setAnimating(boolean isAnimating) {
mIsAnimating = isAnimating;
}
protected float[] getStartValues() {
return mStartValues;
}
protected float[] getStopValues() {
return mStopValues;
}
protected Matrix getWorkingTransform() {
return mWorkingTransform;
}
@Override
public void onGestureBegin(TransformGestureDetector detector) {
FLog.v(getLogTag(), "onGestureBegin");
stopAnimation();
super.onGestureBegin(detector);
}
@Override
public void onGestureUpdate(TransformGestureDetector detector) {
FLog.v(getLogTag(), "onGestureUpdate %s", isAnimating() ? "(ignored)" : "");
if (isAnimating()) {
return;
}
super.onGestureUpdate(detector);
}
protected void calculateInterpolation(Matrix outMatrix, float fraction) {
for (int i = 0; i < 9; i++) {
mCurrentValues[i] = (1 - fraction) * mStartValues[i] + fraction * mStopValues[i];
}
outMatrix.setValues(mCurrentValues);
}
public abstract void setTransformAnimated(
final Matrix newTransform, long durationMs, @Nullable final Runnable onAnimationComplete);
protected abstract void stopAnimation();
protected abstract Class<?> getLogTag();
}