Merge "Fixed OOM due to visibility transitions." into lmp-dev
This commit is contained in:
@@ -23,6 +23,7 @@ import android.graphics.Matrix;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.os.Parcelable;
|
||||
import android.transition.TransitionUtils;
|
||||
import android.view.View;
|
||||
|
||||
import java.util.List;
|
||||
@@ -141,21 +142,12 @@ public abstract class SharedElementCallback {
|
||||
*/
|
||||
public Parcelable onCaptureSharedElementSnapshot(View sharedElement, Matrix viewToGlobalMatrix,
|
||||
RectF screenBounds) {
|
||||
int bitmapWidth = Math.round(screenBounds.width());
|
||||
int bitmapHeight = Math.round(screenBounds.height());
|
||||
Bitmap bitmap = null;
|
||||
if (bitmapWidth > 0 && bitmapHeight > 0) {
|
||||
if (mTempMatrix == null) {
|
||||
mTempMatrix = new Matrix();
|
||||
}
|
||||
if (mTempMatrix == null) {
|
||||
mTempMatrix = new Matrix(viewToGlobalMatrix);
|
||||
} else {
|
||||
mTempMatrix.set(viewToGlobalMatrix);
|
||||
mTempMatrix.postTranslate(-screenBounds.left, -screenBounds.top);
|
||||
bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
canvas.concat(mTempMatrix);
|
||||
sharedElement.draw(canvas);
|
||||
}
|
||||
return bitmap;
|
||||
return TransitionUtils.createViewBitmap(sharedElement, mTempMatrix, screenBounds);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,7 +19,14 @@ package android.transition;
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.TypeEvaluator;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
/**
|
||||
* Static utility methods for Transitions.
|
||||
@@ -27,6 +34,7 @@ import android.graphics.Matrix;
|
||||
* @hide
|
||||
*/
|
||||
public class TransitionUtils {
|
||||
private static int MAX_IMAGE_SIZE = (1024 * 1024);
|
||||
|
||||
static Animator mergeAnimators(Animator animator1, Animator animator2) {
|
||||
if (animator1 == null) {
|
||||
@@ -67,6 +75,70 @@ public class TransitionUtils {
|
||||
return transitionSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a View using the bitmap copy of <code>view</code>. If <code>view</code> is large,
|
||||
* the copy will use a scaled bitmap of the given view.
|
||||
*
|
||||
* @param sceneRoot The ViewGroup in which the view copy will be displayed.
|
||||
* @param view The view to create a copy of.
|
||||
* @param parent The parent of view.
|
||||
*/
|
||||
public static View copyViewImage(ViewGroup sceneRoot, View view, View parent) {
|
||||
Matrix matrix = new Matrix();
|
||||
matrix.setTranslate(-parent.getScrollX(), -parent.getScrollY());
|
||||
view.transformMatrixToGlobal(matrix);
|
||||
sceneRoot.transformMatrixToLocal(matrix);
|
||||
RectF bounds = new RectF(0, 0, view.getWidth(), view.getHeight());
|
||||
matrix.mapRect(bounds);
|
||||
int left = Math.round(bounds.left);
|
||||
int top = Math.round(bounds.top);
|
||||
int right = Math.round(bounds.right);
|
||||
int bottom = Math.round(bounds.bottom);
|
||||
|
||||
ImageView copy = new ImageView(view.getContext());
|
||||
copy.setScaleType(ImageView.ScaleType.CENTER_CROP);
|
||||
Bitmap bitmap = createViewBitmap(view, matrix, bounds);
|
||||
if (bitmap != null) {
|
||||
copy.setImageBitmap(bitmap);
|
||||
}
|
||||
int widthSpec = View.MeasureSpec.makeMeasureSpec(right - left, View.MeasureSpec.EXACTLY);
|
||||
int heightSpec = View.MeasureSpec.makeMeasureSpec(bottom - top, View.MeasureSpec.EXACTLY);
|
||||
copy.measure(widthSpec, heightSpec);
|
||||
copy.layout(left, top, right, bottom);
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Bitmap of the given view, using the Matrix matrix to transform to the local
|
||||
* coordinates. <code>matrix</code> will be modified during the bitmap creation.
|
||||
*
|
||||
* <p>If the bitmap is large, it will be scaled uniformly down to at most 1MB size.</p>
|
||||
* @param view The view to create a bitmap for.
|
||||
* @param matrix The matrix converting the view local coordinates to the coordinates that
|
||||
* the bitmap will be displayed in. <code>matrix</code> will be modified before
|
||||
* returning.
|
||||
* @param bounds The bounds of the bitmap in the destination coordinate system (where the
|
||||
* view should be presented. Typically, this is matrix.mapRect(viewBounds);
|
||||
* @return A bitmap of the given view or null if bounds has no width or height.
|
||||
*/
|
||||
public static Bitmap createViewBitmap(View view, Matrix matrix, RectF bounds) {
|
||||
Bitmap bitmap = null;
|
||||
int bitmapWidth = Math.round(bounds.width());
|
||||
int bitmapHeight = Math.round(bounds.height());
|
||||
if (bitmapWidth > 0 && bitmapHeight > 0) {
|
||||
float scale = Math.min(1f, ((float)MAX_IMAGE_SIZE) / (bitmapWidth * bitmapHeight));
|
||||
bitmapWidth *= scale;
|
||||
bitmapHeight *= scale;
|
||||
matrix.postTranslate(-bounds.left, -bounds.top);
|
||||
matrix.postScale(scale, scale);
|
||||
bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
canvas.concat(matrix);
|
||||
view.draw(canvas);
|
||||
}
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
public static class MatrixEvaluator implements TypeEvaluator<Matrix> {
|
||||
|
||||
float[] mTempStartValues = new float[9];
|
||||
|
||||
@@ -224,11 +224,10 @@ public abstract class Visibility extends Transition {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (startValues == null) {
|
||||
} else if (startValues == null && visInfo.endVisibility == View.VISIBLE) {
|
||||
visInfo.fadeIn = true;
|
||||
visInfo.visibilityChange = true;
|
||||
} else if (endValues == null) {
|
||||
} else if (endValues == null && visInfo.startVisibility == View.VISIBLE) {
|
||||
visInfo.fadeIn = false;
|
||||
visInfo.visibilityChange = true;
|
||||
}
|
||||
@@ -370,16 +369,14 @@ public abstract class Visibility extends Transition {
|
||||
overlayView = startView;
|
||||
} else if (startView.getParent() instanceof View) {
|
||||
View startParent = (View) startView.getParent();
|
||||
VisibilityInfo parentVisibilityInfo = null;
|
||||
TransitionValues startParentValues = getTransitionValues(startParent, true);
|
||||
TransitionValues endParentValues = getMatchedTransitionValues(startParent,
|
||||
true);
|
||||
if (endParentValues != null) {
|
||||
TransitionValues startParentValues = getTransitionValues(startParent, true);
|
||||
parentVisibilityInfo =
|
||||
getVisibilityChangeInfo(startParentValues, endParentValues);
|
||||
}
|
||||
if (parentVisibilityInfo == null || !parentVisibilityInfo.visibilityChange) {
|
||||
overlayView = copyViewImage(startView);
|
||||
VisibilityInfo parentVisibilityInfo =
|
||||
getVisibilityChangeInfo(startParentValues, endParentValues);
|
||||
if (!parentVisibilityInfo.visibilityChange) {
|
||||
overlayView = TransitionUtils.copyViewImage(sceneRoot, startView,
|
||||
startParent);
|
||||
} else if (startParent.getParent() == null) {
|
||||
int id = startParent.getId();
|
||||
if (id != View.NO_ID && sceneRoot.findViewById(id) != null
|
||||
@@ -485,26 +482,6 @@ public abstract class Visibility extends Transition {
|
||||
return null;
|
||||
}
|
||||
|
||||
private View copyViewImage(View view) {
|
||||
int width = view.getWidth();
|
||||
int height = view.getHeight();
|
||||
if (width <= 0 || height <= 0) {
|
||||
return null;
|
||||
}
|
||||
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
view.draw(canvas);
|
||||
final BitmapDrawable drawable = new BitmapDrawable(bitmap);
|
||||
|
||||
View overlayView = new View(view.getContext());
|
||||
overlayView.setBackground(drawable);
|
||||
int widthSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
|
||||
int heightSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY);
|
||||
overlayView.measure(widthSpec, heightSpec);
|
||||
overlayView.layout(0, 0, width, height);
|
||||
return overlayView;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean areValuesChanged(TransitionValues oldValues, TransitionValues newValues) {
|
||||
VisibilityInfo changeInfo = getVisibilityChangeInfo(oldValues, newValues);
|
||||
|
||||
Reference in New Issue
Block a user