Fixes for ImageView drawable visibility dispatch am: 06f9eb8b62

am: fd86f7fdfd

Change-Id: I155ed970c7f58895419778f01eebc5babb141c33
This commit is contained in:
Adam Powell
2016-08-27 01:25:05 +00:00
committed by android-build-merger
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
* @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;
// If we're not visible but something is telling us we are, ignore it.
if (thisVisible || !isVisible) {
@@ -15527,7 +15527,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (vis != GONE) {
onWindowVisibilityChanged(vis);
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
onVisibilityAggregated(vis == VISIBLE);
}

View File

@@ -52,7 +52,6 @@ import android.hardware.input.InputManager;
import android.media.AudioManager;
import android.os.Binder;
import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.Debug;
import android.os.Handler;
@@ -1468,6 +1467,8 @@ public final class ViewRootImpl implements ViewParent,
final int viewVisibility = getHostVisibility();
final boolean viewVisibilityChanged = !mFirst
&& (mViewVisibility != viewVisibility || mNewSurfaceNeeded);
final boolean viewUserVisibilityChanged = !mFirst &&
((mViewVisibility == View.VISIBLE) != (viewVisibility == View.VISIBLE));
WindowManager.LayoutParams params = null;
if (mWindowAttributesChanged) {
@@ -1541,13 +1542,7 @@ public final class ViewRootImpl implements ViewParent,
if (viewVisibilityChanged) {
mAttachInfo.mWindowVisibility = viewVisibility;
host.dispatchWindowVisibilityChanged(viewVisibility);
// 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) {
if (viewUserVisibilityChanged) {
host.dispatchVisibilityAggregated(viewVisibility == View.VISIBLE);
}
if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) {

View File

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