186 lines
6.8 KiB
Java
186 lines
6.8 KiB
Java
/*
|
|
* Copyright (C) 2014 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
package android.transition;
|
|
|
|
import android.animation.Animator;
|
|
import android.animation.ObjectAnimator;
|
|
import android.animation.TypeEvaluator;
|
|
import android.annotation.NonNull;
|
|
import android.annotation.Nullable;
|
|
import android.content.Context;
|
|
import android.graphics.Matrix;
|
|
import android.graphics.Rect;
|
|
import android.graphics.drawable.Drawable;
|
|
import android.util.AttributeSet;
|
|
import android.util.Property;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.widget.ImageView;
|
|
|
|
import java.util.Map;
|
|
|
|
/**
|
|
* This Transition captures an ImageView's matrix before and after the
|
|
* scene change and animates it during the transition.
|
|
*
|
|
* <p>In combination with ChangeBounds, ChangeImageTransform allows ImageViews
|
|
* that change size, shape, or {@link android.widget.ImageView.ScaleType} to animate contents
|
|
* smoothly.</p>
|
|
*/
|
|
public class ChangeImageTransform extends Transition {
|
|
|
|
private static final String TAG = "ChangeImageTransform";
|
|
|
|
private static final String PROPNAME_MATRIX = "android:changeImageTransform:matrix";
|
|
private static final String PROPNAME_BOUNDS = "android:changeImageTransform:bounds";
|
|
|
|
private static final String[] sTransitionProperties = {
|
|
PROPNAME_MATRIX,
|
|
PROPNAME_BOUNDS,
|
|
};
|
|
|
|
private static TypeEvaluator<Matrix> NULL_MATRIX_EVALUATOR = new TypeEvaluator<Matrix>() {
|
|
@Override
|
|
public Matrix evaluate(float fraction, Matrix startValue, Matrix endValue) {
|
|
return null;
|
|
}
|
|
};
|
|
|
|
private static Property<ImageView, Matrix> ANIMATED_TRANSFORM_PROPERTY
|
|
= new Property<ImageView, Matrix>(Matrix.class, "animatedTransform") {
|
|
@Override
|
|
public void set(ImageView object, Matrix value) {
|
|
object.animateTransform(value);
|
|
}
|
|
|
|
@Override
|
|
public Matrix get(ImageView object) {
|
|
return null;
|
|
}
|
|
};
|
|
|
|
public ChangeImageTransform() {}
|
|
|
|
public ChangeImageTransform(Context context, AttributeSet attrs) {
|
|
super(context, attrs);
|
|
}
|
|
|
|
private void captureValues(TransitionValues transitionValues) {
|
|
View view = transitionValues.view;
|
|
if (!(view instanceof ImageView) || view.getVisibility() != View.VISIBLE) {
|
|
return;
|
|
}
|
|
ImageView imageView = (ImageView) view;
|
|
Drawable drawable = imageView.getDrawable();
|
|
if (drawable == null) {
|
|
return;
|
|
}
|
|
Map<String, Object> values = transitionValues.values;
|
|
|
|
int left = view.getLeft();
|
|
int top = view.getTop();
|
|
int right = view.getRight();
|
|
int bottom = view.getBottom();
|
|
|
|
Rect bounds = new Rect(left, top, right, bottom);
|
|
values.put(PROPNAME_BOUNDS, bounds);
|
|
Matrix matrix;
|
|
ImageView.ScaleType scaleType = imageView.getScaleType();
|
|
int drawableWidth = drawable.getIntrinsicWidth();
|
|
int drawableHeight = drawable.getIntrinsicHeight();
|
|
if (scaleType == ImageView.ScaleType.FIT_XY && drawableWidth > 0 && drawableHeight > 0) {
|
|
float scaleX = ((float) bounds.width()) / drawableWidth;
|
|
float scaleY = ((float) bounds.height()) / drawableHeight;
|
|
matrix = new Matrix();
|
|
matrix.setScale(scaleX, scaleY);
|
|
} else {
|
|
matrix = new Matrix(imageView.getImageMatrix());
|
|
}
|
|
values.put(PROPNAME_MATRIX, matrix);
|
|
}
|
|
|
|
@Override
|
|
public void captureStartValues(TransitionValues transitionValues) {
|
|
captureValues(transitionValues);
|
|
}
|
|
|
|
@Override
|
|
public void captureEndValues(TransitionValues transitionValues) {
|
|
captureValues(transitionValues);
|
|
}
|
|
|
|
@Override
|
|
public String[] getTransitionProperties() {
|
|
return sTransitionProperties;
|
|
}
|
|
|
|
/**
|
|
* Creates an Animator for ImageViews moving, changing dimensions, and/or changing
|
|
* {@link android.widget.ImageView.ScaleType}.
|
|
*
|
|
* @param sceneRoot The root of the transition hierarchy.
|
|
* @param startValues The values for a specific target in the start scene.
|
|
* @param endValues The values for the target in the end scene.
|
|
* @return An Animator to move an ImageView or null if the View is not an ImageView,
|
|
* the Drawable changed, the View is not VISIBLE, or there was no change.
|
|
*/
|
|
@Nullable
|
|
@Override
|
|
public Animator createAnimator(@NonNull ViewGroup sceneRoot,
|
|
@Nullable TransitionValues startValues,
|
|
@Nullable TransitionValues endValues) {
|
|
if (startValues == null || endValues == null) {
|
|
return null;
|
|
}
|
|
Rect startBounds = (Rect) startValues.values.get(PROPNAME_BOUNDS);
|
|
Rect endBounds = (Rect) endValues.values.get(PROPNAME_BOUNDS);
|
|
Matrix startMatrix = (Matrix) startValues.values.get(PROPNAME_MATRIX);
|
|
Matrix endMatrix = (Matrix) endValues.values.get(PROPNAME_MATRIX);
|
|
if (startBounds == null || endBounds == null || startMatrix == null || endMatrix == null) {
|
|
return null;
|
|
}
|
|
|
|
if (startBounds.equals(endBounds) && startMatrix.equals(endMatrix)) {
|
|
return null;
|
|
}
|
|
|
|
ImageView imageView = (ImageView) endValues.view;
|
|
Drawable drawable = imageView.getDrawable();
|
|
int drawableWidth = drawable.getIntrinsicWidth();
|
|
int drawableHeight = drawable.getIntrinsicHeight();
|
|
|
|
ObjectAnimator animator;
|
|
if (drawableWidth <= 0 || drawableHeight <= 0) {
|
|
animator = createNullAnimator(imageView);
|
|
} else {
|
|
ANIMATED_TRANSFORM_PROPERTY.set(imageView, startMatrix);
|
|
animator = createMatrixAnimator(imageView, startMatrix, endMatrix);
|
|
}
|
|
return animator;
|
|
}
|
|
|
|
private ObjectAnimator createNullAnimator(ImageView imageView) {
|
|
return ObjectAnimator.ofObject(imageView, ANIMATED_TRANSFORM_PROPERTY,
|
|
NULL_MATRIX_EVALUATOR, Matrix.IDENTITY_MATRIX, Matrix.IDENTITY_MATRIX);
|
|
}
|
|
|
|
private ObjectAnimator createMatrixAnimator(final ImageView imageView, Matrix startMatrix,
|
|
final Matrix endMatrix) {
|
|
return ObjectAnimator.ofObject(imageView, ANIMATED_TRANSFORM_PROPERTY,
|
|
new TransitionUtils.MatrixEvaluator(), startMatrix, endMatrix);
|
|
}
|
|
}
|