Skip to content

Instantly share code, notes, and snippets.

@burzumrus
Last active April 25, 2017 18:56
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save burzumrus/a589aa7e36ca003ddaf2334218c50ad0 to your computer and use it in GitHub Desktop.
Save burzumrus/a589aa7e36ca003ddaf2334218c50ad0 to your computer and use it in GitHub Desktop.
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.os.Build;
import android.transition.Transition;
import android.transition.TransitionValues;
import android.view.ViewGroup;
import com.facebook.drawee.drawable.ScalingUtils;
import com.facebook.drawee.view.GenericDraweeView;
import ru.ok.tamtam.utils.Log;
@TargetApi(Build.VERSION_CODES.KITKAT)
public class DraweeTransform extends Transition {
private static final String PROPNAME_BOUNDS = "draweeTransform:bounds";
private final ScalingUtils.ScaleType fromScale;
private final ScalingUtils.ScaleType toScale;
public DraweeTransform(ScalingUtils.ScaleType fromScale, ScalingUtils.ScaleType toScale) {
this.fromScale = fromScale;
this.toScale = toScale;
}
private void captureValues(TransitionValues transitionValues) {
if (transitionValues.view instanceof GenericDraweeView) {
transitionValues.values.put(PROPNAME_BOUNDS, new Rect(0, 0, transitionValues.view.getWidth(), transitionValues.view.getHeight()));
}
}
@Override
public void captureStartValues(TransitionValues transitionValues) {
captureValues(transitionValues);
}
@Override
public void captureEndValues(TransitionValues transitionValues) {
captureValues(transitionValues);
}
@Override
public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues, TransitionValues endValues) {
if (startValues == null || endValues == null || !(startValues.view instanceof GenericDraweeView)) {
return null;
}
GenericDraweeView draweeView = (GenericDraweeView) startValues.view;
Rect startBounds = (Rect) startValues.values.get(PROPNAME_BOUNDS);
Rect endBounds = (Rect) endValues.values.get(PROPNAME_BOUNDS);
InterpolatingScaleType scaleType = new InterpolatingScaleType(fromScale, toScale, startBounds, endBounds);
draweeView.getHierarchy().setActualImageScaleType(scaleType);
ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
animator.addUpdateListener(animation -> {
float fraction = (float) animation.getAnimatedValue();
scaleType.setValue(fraction);
});
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
draweeView.getHierarchy().setActualImageScaleType(toScale);
}
});
return animator;
}
public static class InterpolatingScaleType implements ScalingUtils.ScaleType {
private final ScalingUtils.ScaleType mScaleTypeFrom;
private final ScalingUtils.ScaleType mScaleTypeTo;
private final Rect mStartBounds;
private final Rect mEndBounds;
private final float[] mMatrixValuesFrom = new float[9];
private final float[] mMatrixValuesTo = new float[9];
private final float[] mMatrixValuesInterpolated = new float[9];
private float mInterpolatingValue;
public InterpolatingScaleType(ScalingUtils.ScaleType scaleTypeFrom, ScalingUtils.ScaleType scaleTypeTo, Rect startBounds, Rect endBounds) {
mScaleTypeFrom = scaleTypeFrom;
mScaleTypeTo = scaleTypeTo;
mStartBounds = startBounds;
mEndBounds = endBounds;
}
public void setValue(float value) {
mInterpolatingValue = value;
}
@Override
public Matrix getTransform(
Matrix transform,
Rect parentBounds,
int childWidth,
int childHeight,
float focusX,
float focusY) {
mScaleTypeFrom.getTransform(transform, mStartBounds, childWidth, childHeight, focusX, focusY);
transform.getValues(mMatrixValuesFrom);
mScaleTypeTo.getTransform(transform, mEndBounds, childWidth, childHeight, focusX, focusY);
transform.getValues(mMatrixValuesTo);
for (int i = 0; i < 9; i++) {
mMatrixValuesInterpolated[i] = mMatrixValuesFrom[i] * (1 - mInterpolatingValue) +
mMatrixValuesTo[i] * mInterpolatingValue;
}
transform.setValues(mMatrixValuesInterpolated);
Log.d("MATRIX", transform.toString());
return transform;
}
}
}
@plamenko
Copy link

plamenko commented May 14, 2016

This is amazing, thanks a lot for implementing it!

Btw, you do not need to pass in the scaleTypeFrom. You can get it with draweeView.getHierarchy().getActualImageScaleType() while capturing. Same for scaleTypeTo.

Also, for ease of usage, consider making a static factory method here that will create the necessary TransitionSet.

public static TransitionSet createTransitionSet() {
  TransitionSet transitionSet = new TransitionSet();
  transitionSet.addTransition(new ChangeBounds());
  transitionSet.addTransition(new DraweeTransform());
  return transitionSet;
}

Then in the client code you only need to do: getWindow().setSharedElementEnterTransition(DraweeTransform.createTransitionSet());.

@plamenko
Copy link

And please, make a pull request for Fresco lib, we will accept it immediately :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment