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;
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) {
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) {
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;
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,
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
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 {
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);
}
}
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();
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);
}
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);
}
@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();