Merge "Fixes for ImageView drawable visibility dispatch" into nyc-dr1-dev

This commit is contained in:
Daniel Chapin
2016-08-27 01:14:33 +00:00
committed by Android (Google) Code Review
3 changed files with 65 additions and 25 deletions

View File

@@ -10384,7 +10384,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* ancestors or by window visibility * ancestors or by window visibility
* @return true if this view is visible to the user, not counting clipping or overlapping * @return true if this view is visible to the user, not counting clipping or overlapping
*/ */
@Visibility boolean dispatchVisibilityAggregated(boolean isVisible) { boolean dispatchVisibilityAggregated(boolean isVisible) {
final boolean thisVisible = getVisibility() == VISIBLE; final boolean thisVisible = getVisibility() == VISIBLE;
// If we're not visible but something is telling us we are, ignore it. // If we're not visible but something is telling us we are, ignore it.
if (thisVisible || !isVisible) { if (thisVisible || !isVisible) {
@@ -15527,7 +15527,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (vis != GONE) { if (vis != GONE) {
onWindowVisibilityChanged(vis); onWindowVisibilityChanged(vis);
if (isShown()) { if (isShown()) {
// Calling onVisibilityChanged directly here since the subtree will also // Calling onVisibilityAggregated directly here since the subtree will also
// receive dispatchAttachedToWindow and this same call // receive dispatchAttachedToWindow and this same call
onVisibilityAggregated(vis == VISIBLE); onVisibilityAggregated(vis == VISIBLE);
} }

View File

@@ -52,7 +52,6 @@ import android.hardware.input.InputManager;
import android.media.AudioManager; import android.media.AudioManager;
import android.os.Binder; import android.os.Binder;
import android.os.Build; import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.os.Bundle; import android.os.Bundle;
import android.os.Debug; import android.os.Debug;
import android.os.Handler; import android.os.Handler;
@@ -1468,6 +1467,8 @@ public final class ViewRootImpl implements ViewParent,
final int viewVisibility = getHostVisibility(); final int viewVisibility = getHostVisibility();
final boolean viewVisibilityChanged = !mFirst final boolean viewVisibilityChanged = !mFirst
&& (mViewVisibility != viewVisibility || mNewSurfaceNeeded); && (mViewVisibility != viewVisibility || mNewSurfaceNeeded);
final boolean viewUserVisibilityChanged = !mFirst &&
((mViewVisibility == View.VISIBLE) != (viewVisibility == View.VISIBLE));
WindowManager.LayoutParams params = null; WindowManager.LayoutParams params = null;
if (mWindowAttributesChanged) { if (mWindowAttributesChanged) {
@@ -1541,13 +1542,7 @@ public final class ViewRootImpl implements ViewParent,
if (viewVisibilityChanged) { if (viewVisibilityChanged) {
mAttachInfo.mWindowVisibility = viewVisibility; mAttachInfo.mWindowVisibility = viewVisibility;
host.dispatchWindowVisibilityChanged(viewVisibility); host.dispatchWindowVisibilityChanged(viewVisibility);
if (viewUserVisibilityChanged) {
// Prior to N we didn't have dispatchVisibilityAggregated to give a more accurate
// view into when views are visible to the user or not. ImageView never dealt with
// telling its drawable about window visibility, among other things. Some apps cause
// an additional crossfade animation when windows become visible if they get this
// additional call, so only send it to new apps to avoid new visual jank.
if (host.getContext().getApplicationInfo().targetSdkVersion >= VERSION_CODES.N) {
host.dispatchVisibilityAggregated(viewVisibility == View.VISIBLE); host.dispatchVisibilityAggregated(viewVisibility == View.VISIBLE);
} }
if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) { if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) {

View File

@@ -22,7 +22,6 @@ import android.annotation.Nullable;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.content.res.ColorStateList; import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Canvas; import android.graphics.Canvas;
@@ -115,11 +114,17 @@ public class ImageView extends View {
private int mBaseline = -1; private int mBaseline = -1;
private boolean mBaselineAlignBottom = false; private boolean mBaselineAlignBottom = false;
// AdjustViewBounds behavior will be in compatibility mode for older apps. /** Compatibility modes dependent on targetSdkVersion of the app. */
private boolean mAdjustViewBoundsCompat = false; private static boolean sCompatDone;
/** AdjustViewBounds behavior will be in compatibility mode for older apps. */
private static boolean sCompatAdjustViewBounds;
/** Whether to pass Resources when creating the source from a stream. */ /** Whether to pass Resources when creating the source from a stream. */
private boolean mUseCorrectStreamDensity; private static boolean sCompatUseCorrectStreamDensity;
/** Whether to use pre-Nougat drawable visibility dispatching conditions. */
private static boolean sCompatDrawableVisibilityDispatch;
private static final ScaleType[] sScaleTypeArray = { private static final ScaleType[] sScaleTypeArray = {
ScaleType.MATRIX, ScaleType.MATRIX,
@@ -206,9 +211,13 @@ public class ImageView extends View {
mMatrix = new Matrix(); mMatrix = new Matrix();
mScaleType = ScaleType.FIT_CENTER; mScaleType = ScaleType.FIT_CENTER;
final int targetSdkVersion = mContext.getApplicationInfo().targetSdkVersion; if (!sCompatDone) {
mAdjustViewBoundsCompat = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1; final int targetSdkVersion = mContext.getApplicationInfo().targetSdkVersion;
mUseCorrectStreamDensity = targetSdkVersion > Build.VERSION_CODES.M; sCompatAdjustViewBounds = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1;
sCompatUseCorrectStreamDensity = targetSdkVersion > Build.VERSION_CODES.M;
sCompatDrawableVisibilityDispatch = targetSdkVersion < Build.VERSION_CODES.N;
sCompatDone = true;
}
} }
@Override @Override
@@ -881,8 +890,8 @@ public class ImageView extends View {
InputStream stream = null; InputStream stream = null;
try { try {
stream = mContext.getContentResolver().openInputStream(uri); stream = mContext.getContentResolver().openInputStream(uri);
return Drawable.createFromResourceStream( return Drawable.createFromResourceStream(sCompatUseCorrectStreamDensity
mUseCorrectStreamDensity ? getResources() : null, null, stream, null); ? getResources() : null, null, stream, null);
} catch (Exception e) { } catch (Exception e) {
Log.w(LOG_TAG, "Unable to open content: " + uri, e); Log.w(LOG_TAG, "Unable to open content: " + uri, e);
} finally { } finally {
@@ -917,10 +926,13 @@ public class ImageView extends View {
mRecycleableBitmapDrawable.setBitmap(null); mRecycleableBitmapDrawable.setBitmap(null);
} }
boolean sameDrawable = false;
if (mDrawable != null) { if (mDrawable != null) {
sameDrawable = mDrawable == d;
mDrawable.setCallback(null); mDrawable.setCallback(null);
unscheduleDrawable(mDrawable); unscheduleDrawable(mDrawable);
if (isAttachedToWindow()) { if (!sCompatDrawableVisibilityDispatch && !sameDrawable && isAttachedToWindow()) {
mDrawable.setVisible(false, false); mDrawable.setVisible(false, false);
} }
} }
@@ -933,8 +945,12 @@ public class ImageView extends View {
if (d.isStateful()) { if (d.isStateful()) {
d.setState(getDrawableState()); d.setState(getDrawableState());
} }
d.setVisible(isAttachedToWindow() && getWindowVisibility() == VISIBLE && isShown(), if (!sameDrawable || sCompatDrawableVisibilityDispatch) {
true); final boolean visible = sCompatDrawableVisibilityDispatch
? getVisibility() == VISIBLE
: isAttachedToWindow() && getWindowVisibility() == VISIBLE && isShown();
d.setVisible(visible, true);
}
d.setLevel(mLevel); d.setLevel(mLevel);
mDrawableWidth = d.getIntrinsicWidth(); mDrawableWidth = d.getIntrinsicWidth();
mDrawableHeight = d.getIntrinsicHeight(); mDrawableHeight = d.getIntrinsicHeight();
@@ -1057,7 +1073,7 @@ public class ImageView extends View {
pleft + pright; pleft + pright;
// Allow the width to outgrow its original estimate if height is fixed. // Allow the width to outgrow its original estimate if height is fixed.
if (!resizeHeight && !mAdjustViewBoundsCompat) { if (!resizeHeight && !sCompatAdjustViewBounds) {
widthSize = resolveAdjustedSize(newWidth, mMaxWidth, widthMeasureSpec); widthSize = resolveAdjustedSize(newWidth, mMaxWidth, widthMeasureSpec);
} }
@@ -1073,7 +1089,7 @@ public class ImageView extends View {
ptop + pbottom; ptop + pbottom;
// Allow the height to outgrow its original estimate if width is fixed. // Allow the height to outgrow its original estimate if width is fixed.
if (!resizeWidth && !mAdjustViewBoundsCompat) { if (!resizeWidth && !sCompatAdjustViewBounds) {
heightSize = resolveAdjustedSize(newHeight, mMaxHeight, heightSize = resolveAdjustedSize(newHeight, mMaxHeight,
heightMeasureSpec); heightMeasureSpec);
} }
@@ -1512,11 +1528,40 @@ public class ImageView extends View {
@Override @Override
public void onVisibilityAggregated(boolean isVisible) { public void onVisibilityAggregated(boolean isVisible) {
super.onVisibilityAggregated(isVisible); super.onVisibilityAggregated(isVisible);
if (mDrawable != null) { // Only do this for new apps post-Nougat
if (mDrawable != null && !sCompatDrawableVisibilityDispatch) {
mDrawable.setVisible(isVisible, false); mDrawable.setVisible(isVisible, false);
} }
} }
@RemotableViewMethod
@Override
public void setVisibility(int visibility) {
super.setVisibility(visibility);
// Only do this for old apps pre-Nougat; new apps use onVisibilityAggregated
if (mDrawable != null && sCompatDrawableVisibilityDispatch) {
mDrawable.setVisible(visibility == VISIBLE, false);
}
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
// Only do this for old apps pre-Nougat; new apps use onVisibilityAggregated
if (mDrawable != null && sCompatDrawableVisibilityDispatch) {
mDrawable.setVisible(getVisibility() == VISIBLE, false);
}
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
// Only do this for old apps pre-Nougat; new apps use onVisibilityAggregated
if (mDrawable != null && sCompatDrawableVisibilityDispatch) {
mDrawable.setVisible(false, false);
}
}
@Override @Override
public CharSequence getAccessibilityClassName() { public CharSequence getAccessibilityClassName() {
return ImageView.class.getName(); return ImageView.class.getName();