Merge "Propagate density through AdaptiveIconDrawable and BitmapDrawable" into oc-dev
am: 5be3647a9e
Change-Id: Ie0408d44a2641e704c18399c996aff7f996e2764
This commit is contained in:
@@ -815,14 +815,7 @@ public class Resources {
|
||||
*/
|
||||
public Drawable getDrawable(@DrawableRes int id, @Nullable Theme theme)
|
||||
throws NotFoundException {
|
||||
final TypedValue value = obtainTempTypedValue();
|
||||
try {
|
||||
final ResourcesImpl impl = mResourcesImpl;
|
||||
impl.getValue(id, value, true);
|
||||
return impl.loadDrawable(this, value, id, theme, true);
|
||||
} finally {
|
||||
releaseTempTypedValue(value);
|
||||
}
|
||||
return getDrawableForDensity(id, 0, theme);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -844,7 +837,9 @@ public class Resources {
|
||||
* This integer encodes the package, type, and resource entry.
|
||||
* The value 0 is an invalid identifier.
|
||||
* @param density the desired screen density indicated by the resource as
|
||||
* found in {@link DisplayMetrics}.
|
||||
* found in {@link DisplayMetrics}. A value of 0 means to use the
|
||||
* density returned from {@link #getConfiguration()}.
|
||||
* This is equivalent to calling {@link #getDrawable(int)}.
|
||||
* @return Drawable An object that can be used to draw this resource.
|
||||
* @throws NotFoundException Throws NotFoundException if the given ID does
|
||||
* not exist.
|
||||
@@ -865,7 +860,9 @@ public class Resources {
|
||||
* This integer encodes the package, type, and resource entry.
|
||||
* The value 0 is an invalid identifier.
|
||||
* @param density The desired screen density indicated by the resource as
|
||||
* found in {@link DisplayMetrics}.
|
||||
* found in {@link DisplayMetrics}. A value of 0 means to use the
|
||||
* density returned from {@link #getConfiguration()}.
|
||||
* This is equivalent to calling {@link #getDrawable(int, Theme)}.
|
||||
* @param theme The theme used to style the drawable attributes, may be {@code null}.
|
||||
* @return Drawable An object that can be used to draw this resource.
|
||||
* @throws NotFoundException Throws NotFoundException if the given ID does
|
||||
@@ -876,37 +873,16 @@ public class Resources {
|
||||
try {
|
||||
final ResourcesImpl impl = mResourcesImpl;
|
||||
impl.getValueForDensity(id, density, value, true);
|
||||
|
||||
// If the drawable's XML lives in our current density qualifier,
|
||||
// it's okay to use a scaled version from the cache. Otherwise, we
|
||||
// need to actually load the drawable from XML.
|
||||
final DisplayMetrics metrics = impl.getDisplayMetrics();
|
||||
final boolean useCache = value.density == metrics.densityDpi;
|
||||
|
||||
/*
|
||||
* Pretend the requested density is actually the display density. If
|
||||
* the drawable returned is not the requested density, then force it
|
||||
* to be scaled later by dividing its density by the ratio of
|
||||
* requested density to actual device density. Drawables that have
|
||||
* undefined density or no density don't need to be handled here.
|
||||
*/
|
||||
if (value.density > 0 && value.density != TypedValue.DENSITY_NONE) {
|
||||
if (value.density == density) {
|
||||
value.density = metrics.densityDpi;
|
||||
} else {
|
||||
value.density = (value.density * metrics.densityDpi) / density;
|
||||
}
|
||||
}
|
||||
return impl.loadDrawable(this, value, id, theme, useCache);
|
||||
return impl.loadDrawable(this, value, id, density, theme);
|
||||
} finally {
|
||||
releaseTempTypedValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
Drawable loadDrawable(@NonNull TypedValue value, int id, @Nullable Theme theme)
|
||||
Drawable loadDrawable(@NonNull TypedValue value, int id, int density, @Nullable Theme theme)
|
||||
throws NotFoundException {
|
||||
return mResourcesImpl.loadDrawable(this, value, id, theme, true);
|
||||
return mResourcesImpl.loadDrawable(this, value, id, density, theme);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1221,8 +1197,7 @@ public class Resources {
|
||||
* used to open drawable, sound, and raw resources; it will fail on string
|
||||
* and color resources.
|
||||
*
|
||||
* @param id The resource identifier to open, as generated by the appt
|
||||
* tool.
|
||||
* @param id The resource identifier to open, as generated by the aapt tool.
|
||||
*
|
||||
* @return InputStream Access to the resource data.
|
||||
*
|
||||
@@ -1278,7 +1253,7 @@ public class Resources {
|
||||
* used to open drawable, sound, and raw resources; it will fail on string
|
||||
* and color resources.
|
||||
*
|
||||
* @param id The resource identifier to open, as generated by the appt tool.
|
||||
* @param id The resource identifier to open, as generated by the aapt tool.
|
||||
* @param value The TypedValue object to hold the resource information.
|
||||
*
|
||||
* @return InputStream Access to the resource data.
|
||||
@@ -1300,8 +1275,7 @@ public class Resources {
|
||||
* as uncompressed data, which typically includes things like mp3 files
|
||||
* and png images.
|
||||
*
|
||||
* @param id The resource identifier to open, as generated by the appt
|
||||
* tool.
|
||||
* @param id The resource identifier to open, as generated by the aapt tool.
|
||||
*
|
||||
* @return AssetFileDescriptor A new file descriptor you can use to read
|
||||
* the resource. This includes the file descriptor itself, as well as the
|
||||
|
||||
@@ -523,8 +523,27 @@ public class ResourcesImpl {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
Drawable loadDrawable(Resources wrapper, TypedValue value, int id, Resources.Theme theme,
|
||||
boolean useCache) throws NotFoundException {
|
||||
Drawable loadDrawable(@NonNull Resources wrapper, @NonNull TypedValue value, int id,
|
||||
int density, @Nullable Resources.Theme theme)
|
||||
throws NotFoundException {
|
||||
// If the drawable's XML lives in our current density qualifier,
|
||||
// it's okay to use a scaled version from the cache. Otherwise, we
|
||||
// need to actually load the drawable from XML.
|
||||
final boolean useCache = density == 0 || value.density == mMetrics.densityDpi;
|
||||
|
||||
// Pretend the requested density is actually the display density. If
|
||||
// the drawable returned is not the requested density, then force it
|
||||
// to be scaled later by dividing its density by the ratio of
|
||||
// requested density to actual device density. Drawables that have
|
||||
// undefined density or no density don't need to be handled here.
|
||||
if (density > 0 && value.density > 0 && value.density != TypedValue.DENSITY_NONE) {
|
||||
if (value.density == density) {
|
||||
value.density = mMetrics.densityDpi;
|
||||
} else {
|
||||
value.density = (value.density * mMetrics.densityDpi) / density;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (TRACE_FOR_PRELOAD) {
|
||||
// Log only framework resources
|
||||
@@ -576,7 +595,7 @@ public class ResourcesImpl {
|
||||
} else if (isColorDrawable) {
|
||||
dr = new ColorDrawable(value.data);
|
||||
} else {
|
||||
dr = loadDrawableForCookie(wrapper, value, id, null);
|
||||
dr = loadDrawableForCookie(wrapper, value, id, density, null);
|
||||
}
|
||||
|
||||
// Determine if the drawable has unresolved theme attributes. If it
|
||||
@@ -691,8 +710,8 @@ public class ResourcesImpl {
|
||||
/**
|
||||
* Loads a drawable from XML or resources stream.
|
||||
*/
|
||||
private Drawable loadDrawableForCookie(Resources wrapper, TypedValue value, int id,
|
||||
Resources.Theme theme) {
|
||||
private Drawable loadDrawableForCookie(@NonNull Resources wrapper, @NonNull TypedValue value,
|
||||
int id, int density, @Nullable Resources.Theme theme) {
|
||||
if (value.string == null) {
|
||||
throw new NotFoundException("Resource \"" + getResourceName(id) + "\" ("
|
||||
+ Integer.toHexString(id) + ") is not a Drawable (color or path): " + value);
|
||||
@@ -722,7 +741,7 @@ public class ResourcesImpl {
|
||||
if (file.endsWith(".xml")) {
|
||||
final XmlResourceParser rp = loadXmlResourceParser(
|
||||
file, id, value.assetCookie, "drawable");
|
||||
dr = Drawable.createFromXml(wrapper, rp, theme);
|
||||
dr = Drawable.createFromXmlForDensity(wrapper, rp, density, theme);
|
||||
rp.close();
|
||||
} else {
|
||||
final InputStream is = mAssets.openNonAsset(
|
||||
|
||||
@@ -923,6 +923,15 @@ public class TypedArray {
|
||||
*/
|
||||
@Nullable
|
||||
public Drawable getDrawable(@StyleableRes int index) {
|
||||
return getDrawableForDensity(index, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Version of {@link #getDrawable(int)} that accepts an override density.
|
||||
* @hide
|
||||
*/
|
||||
@Nullable
|
||||
public Drawable getDrawableForDensity(@StyleableRes int index, int density) {
|
||||
if (mRecycled) {
|
||||
throw new RuntimeException("Cannot make calls to a recycled instance!");
|
||||
}
|
||||
@@ -933,7 +942,13 @@ public class TypedArray {
|
||||
throw new UnsupportedOperationException(
|
||||
"Failed to resolve attribute at index " + index + ": " + value);
|
||||
}
|
||||
return mResources.loadDrawable(value, value.resourceId, mTheme);
|
||||
|
||||
if (density > 0) {
|
||||
// If the density is overridden, the value in the TypedArray will not reflect this.
|
||||
// Do a separate lookup of the resourceId with the density override.
|
||||
mResources.getValueForDensity(value.resourceId, density, value, true);
|
||||
}
|
||||
return mResources.loadDrawable(value, value.resourceId, density, mTheme);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package android.graphics.drawable;
|
||||
|
||||
import static android.graphics.drawable.Drawable.obtainAttributes;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.TestApi;
|
||||
@@ -218,14 +216,16 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback
|
||||
|
||||
// The density may have changed since the last update. This will
|
||||
// apply scaling to any existing constant state properties.
|
||||
final int density = Drawable.resolveDensity(r, 0);
|
||||
state.setDensity(density);
|
||||
final int deviceDensity = Drawable.resolveDensity(r, 0);
|
||||
state.setDensity(deviceDensity);
|
||||
state.mSrcDensityOverride = mSrcDensityOverride;
|
||||
|
||||
final ChildDrawable[] array = state.mChildren;
|
||||
for (int i = 0; i < state.mChildren.length; i++) {
|
||||
final ChildDrawable layer = array[i];
|
||||
layer.setDensity(density);
|
||||
layer.setDensity(deviceDensity);
|
||||
}
|
||||
|
||||
inflateLayers(r, parser, attrs, theme);
|
||||
}
|
||||
|
||||
@@ -444,7 +444,7 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback
|
||||
/**
|
||||
* Inflates child layers using the specified parser.
|
||||
*/
|
||||
void inflateLayers(@NonNull Resources r, @NonNull XmlPullParser parser,
|
||||
private void inflateLayers(@NonNull Resources r, @NonNull XmlPullParser parser,
|
||||
@NonNull AttributeSet attrs, @Nullable Theme theme)
|
||||
throws XmlPullParserException, IOException {
|
||||
final LayerState state = mLayerState;
|
||||
@@ -491,7 +491,8 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback
|
||||
}
|
||||
|
||||
// We found a child drawable. Take ownership.
|
||||
layer.mDrawable = Drawable.createFromXmlInner(r, parser, attrs, theme);
|
||||
layer.mDrawable = Drawable.createFromXmlInnerForDensity(r, parser, attrs,
|
||||
mLayerState.mSrcDensityOverride, theme);
|
||||
layer.mDrawable.setCallback(this);
|
||||
state.mChildrenChangingConfigurations |=
|
||||
layer.mDrawable.getChangingConfigurations();
|
||||
@@ -509,7 +510,8 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback
|
||||
// Extract the theme attributes, if any.
|
||||
layer.mThemeAttrs = a.extractThemeAttrs();
|
||||
|
||||
Drawable dr = a.getDrawable(R.styleable.AdaptiveIconDrawableLayer_drawable);
|
||||
Drawable dr = a.getDrawableForDensity(R.styleable.AdaptiveIconDrawableLayer_drawable,
|
||||
state.mSrcDensityOverride);
|
||||
if (dr != null) {
|
||||
if (layer.mDrawable != null) {
|
||||
// It's possible that a drawable was already set, in which case
|
||||
@@ -951,7 +953,13 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback
|
||||
final static int N_CHILDREN = 2;
|
||||
ChildDrawable[] mChildren;
|
||||
|
||||
// The density at which to render the drawable and its children.
|
||||
int mDensity;
|
||||
|
||||
// The density to use when inflating/looking up the children drawables. A value of 0 means
|
||||
// use the system's density.
|
||||
int mSrcDensityOverride = 0;
|
||||
|
||||
int mOpacityOverride = PixelFormat.UNKNOWN;
|
||||
|
||||
@Config int mChangingConfigurations;
|
||||
@@ -986,6 +994,7 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback
|
||||
mAutoMirrored = orig.mAutoMirrored;
|
||||
mThemeAttrs = orig.mThemeAttrs;
|
||||
mOpacityOverride = orig.mOpacityOverride;
|
||||
mSrcDensityOverride = orig.mSrcDensityOverride;
|
||||
} else {
|
||||
for (int i = 0; i < N_CHILDREN; i++) {
|
||||
mChildren[i] = new ChildDrawable(mDensity);
|
||||
|
||||
@@ -41,6 +41,7 @@ import android.graphics.Xfermode;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.LayoutDirection;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
|
||||
import com.android.internal.R;
|
||||
@@ -49,6 +50,7 @@ import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* A Drawable that wraps a bitmap and can be tiled, stretched, or aligned. You can create a
|
||||
@@ -749,7 +751,7 @@ public class BitmapDrawable extends Drawable {
|
||||
super.inflate(r, parser, attrs, theme);
|
||||
|
||||
final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.BitmapDrawable);
|
||||
updateStateFromTypedArray(a);
|
||||
updateStateFromTypedArray(a, mSrcDensityOverride);
|
||||
verifyRequiredAttributes(a);
|
||||
a.recycle();
|
||||
|
||||
@@ -775,7 +777,8 @@ public class BitmapDrawable extends Drawable {
|
||||
/**
|
||||
* Updates the constant state from the values in the typed array.
|
||||
*/
|
||||
private void updateStateFromTypedArray(TypedArray a) throws XmlPullParserException {
|
||||
private void updateStateFromTypedArray(TypedArray a, int srcDensityOverride)
|
||||
throws XmlPullParserException {
|
||||
final Resources r = a.getResources();
|
||||
final BitmapState state = mBitmapState;
|
||||
|
||||
@@ -785,9 +788,37 @@ public class BitmapDrawable extends Drawable {
|
||||
// Extract the theme attributes, if any.
|
||||
state.mThemeAttrs = a.extractThemeAttrs();
|
||||
|
||||
state.mSrcDensityOverride = srcDensityOverride;
|
||||
|
||||
state.mTargetDensity = Drawable.resolveDensity(r, 0);
|
||||
|
||||
final int srcResId = a.getResourceId(R.styleable.BitmapDrawable_src, 0);
|
||||
if (srcResId != 0) {
|
||||
final Bitmap bitmap = BitmapFactory.decodeResource(r, srcResId);
|
||||
final TypedValue value = new TypedValue();
|
||||
r.getValueForDensity(srcResId, srcDensityOverride, value, true);
|
||||
|
||||
// Pretend the requested density is actually the display density. If
|
||||
// the drawable returned is not the requested density, then force it
|
||||
// to be scaled later by dividing its density by the ratio of
|
||||
// requested density to actual device density. Drawables that have
|
||||
// undefined density or no density don't need to be handled here.
|
||||
if (srcDensityOverride > 0 && value.density > 0
|
||||
&& value.density != TypedValue.DENSITY_NONE) {
|
||||
if (value.density == srcDensityOverride) {
|
||||
value.density = r.getDisplayMetrics().densityDpi;
|
||||
} else {
|
||||
value.density =
|
||||
(value.density * r.getDisplayMetrics().densityDpi) / srcDensityOverride;
|
||||
}
|
||||
}
|
||||
|
||||
Bitmap bitmap = null;
|
||||
try (InputStream is = r.openRawResource(srcResId, value)) {
|
||||
bitmap = BitmapFactory.decodeResourceStream(r, value, is, null, null);
|
||||
} catch (Exception e) {
|
||||
// Do nothing and pick up the error below.
|
||||
}
|
||||
|
||||
if (bitmap == null) {
|
||||
throw new XmlPullParserException(a.getPositionDescription() +
|
||||
": <bitmap> requires a valid 'src' attribute");
|
||||
@@ -796,8 +827,6 @@ public class BitmapDrawable extends Drawable {
|
||||
state.mBitmap = bitmap;
|
||||
}
|
||||
|
||||
state.mTargetDensity = r.getDisplayMetrics().densityDpi;
|
||||
|
||||
final boolean defMipMap = state.mBitmap != null ? state.mBitmap.hasMipMap() : false;
|
||||
setMipMap(a.getBoolean(R.styleable.BitmapDrawable_mipMap, defMipMap));
|
||||
|
||||
@@ -839,8 +868,6 @@ public class BitmapDrawable extends Drawable {
|
||||
if (tileModeY != TILE_MODE_UNDEFINED) {
|
||||
setTileModeY(parseTileMode(tileModeY));
|
||||
}
|
||||
|
||||
state.mTargetDensity = Drawable.resolveDensity(r, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -855,7 +882,7 @@ public class BitmapDrawable extends Drawable {
|
||||
if (state.mThemeAttrs != null) {
|
||||
final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.BitmapDrawable);
|
||||
try {
|
||||
updateStateFromTypedArray(a);
|
||||
updateStateFromTypedArray(a, state.mSrcDensityOverride);
|
||||
} catch (XmlPullParserException e) {
|
||||
rethrowAsRuntimeException(e);
|
||||
} finally {
|
||||
@@ -929,7 +956,14 @@ public class BitmapDrawable extends Drawable {
|
||||
float mBaseAlpha = 1.0f;
|
||||
Shader.TileMode mTileModeX = null;
|
||||
Shader.TileMode mTileModeY = null;
|
||||
|
||||
// The density to use when looking up the bitmap in Resources. A value of 0 means use
|
||||
// the system's density.
|
||||
int mSrcDensityOverride = 0;
|
||||
|
||||
// The density at which to render the bitmap.
|
||||
int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
|
||||
|
||||
boolean mAutoMirrored = false;
|
||||
|
||||
@Config int mChangingConfigurations;
|
||||
@@ -949,6 +983,7 @@ public class BitmapDrawable extends Drawable {
|
||||
mGravity = bitmapState.mGravity;
|
||||
mTileModeX = bitmapState.mTileModeX;
|
||||
mTileModeY = bitmapState.mTileModeY;
|
||||
mSrcDensityOverride = bitmapState.mSrcDensityOverride;
|
||||
mTargetDensity = bitmapState.mTargetDensity;
|
||||
mBaseAlpha = bitmapState.mBaseAlpha;
|
||||
mPaint = new Paint(bitmapState.mPaint);
|
||||
|
||||
@@ -188,6 +188,21 @@ public abstract class Drawable {
|
||||
|
||||
private int mLayoutDirection;
|
||||
|
||||
/**
|
||||
* The source density to use when looking up resources using
|
||||
* {@link Resources#getDrawableForDensity(int, int, Theme)}. A value of 0 means there is no
|
||||
* override and the system density will be used.
|
||||
*
|
||||
* NOTE(adamlesinski): This is transient state used to get around the public API that does not
|
||||
* account for source density overrides. Custom drawables implemented by developers do not need
|
||||
* to be aware of the source density override, as it is only used by Launcher to load higher
|
||||
* resolution icons from external Resources packages, which do not execute custom code.
|
||||
* This is all to support the {@link Resources#getDrawableForDensity(int, int, Theme)} API.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
protected int mSrcDensityOverride = 0;
|
||||
|
||||
/**
|
||||
* Draw in its bounds (set via setBounds) respecting optional effects such
|
||||
* as alpha (set via setAlpha) and color filter (set via setColorFilter).
|
||||
@@ -1197,7 +1212,8 @@ public abstract class Drawable {
|
||||
* create resources in XML, see
|
||||
* <a href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.
|
||||
*/
|
||||
public static Drawable createFromXml(Resources r, XmlPullParser parser)
|
||||
@NonNull
|
||||
public static Drawable createFromXml(@NonNull Resources r, @NonNull XmlPullParser parser)
|
||||
throws XmlPullParserException, IOException {
|
||||
return createFromXml(r, parser, null);
|
||||
}
|
||||
@@ -1207,7 +1223,20 @@ public abstract class Drawable {
|
||||
* For more information on how to create resources in XML, see
|
||||
* <a href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.
|
||||
*/
|
||||
public static Drawable createFromXml(Resources r, XmlPullParser parser, Theme theme)
|
||||
@NonNull
|
||||
public static Drawable createFromXml(@NonNull Resources r, @NonNull XmlPullParser parser,
|
||||
@Nullable Theme theme) throws XmlPullParserException, IOException {
|
||||
return createFromXmlForDensity(r, parser, 0, theme);
|
||||
}
|
||||
|
||||
/**
|
||||
* Version of {@link #createFromXml(Resources, XmlPullParser, Theme)} that accepts a density
|
||||
* override.
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
public static Drawable createFromXmlForDensity(@NonNull Resources r,
|
||||
@NonNull XmlPullParser parser, int density, @Nullable Theme theme)
|
||||
throws XmlPullParserException, IOException {
|
||||
AttributeSet attrs = Xml.asAttributeSet(parser);
|
||||
|
||||
@@ -1222,7 +1251,7 @@ public abstract class Drawable {
|
||||
throw new XmlPullParserException("No start tag found");
|
||||
}
|
||||
|
||||
Drawable drawable = createFromXmlInner(r, parser, attrs, theme);
|
||||
Drawable drawable = createFromXmlInnerForDensity(r, parser, attrs, density, theme);
|
||||
|
||||
if (drawable == null) {
|
||||
throw new RuntimeException("Unknown initial tag: " + parser.getName());
|
||||
@@ -1236,8 +1265,9 @@ public abstract class Drawable {
|
||||
* a tag in an XML document, tries to create a Drawable from that tag.
|
||||
* Returns null if the tag is not a valid drawable.
|
||||
*/
|
||||
public static Drawable createFromXmlInner(Resources r, XmlPullParser parser, AttributeSet attrs)
|
||||
throws XmlPullParserException, IOException {
|
||||
@NonNull
|
||||
public static Drawable createFromXmlInner(@NonNull Resources r, @NonNull XmlPullParser parser,
|
||||
@NonNull AttributeSet attrs) throws XmlPullParserException, IOException {
|
||||
return createFromXmlInner(r, parser, attrs, null);
|
||||
}
|
||||
|
||||
@@ -1247,14 +1277,29 @@ public abstract class Drawable {
|
||||
* document, tries to create a Drawable from that tag. Returns {@code null}
|
||||
* if the tag is not a valid drawable.
|
||||
*/
|
||||
public static Drawable createFromXmlInner(Resources r, XmlPullParser parser, AttributeSet attrs,
|
||||
Theme theme) throws XmlPullParserException, IOException {
|
||||
return r.getDrawableInflater().inflateFromXml(parser.getName(), parser, attrs, theme);
|
||||
@NonNull
|
||||
public static Drawable createFromXmlInner(@NonNull Resources r, @NonNull XmlPullParser parser,
|
||||
@NonNull AttributeSet attrs, @Nullable Theme theme)
|
||||
throws XmlPullParserException, IOException {
|
||||
return createFromXmlInnerForDensity(r, parser, attrs, 0, theme);
|
||||
}
|
||||
|
||||
/**
|
||||
* Version of {@link #createFromXmlInner(Resources, XmlPullParser, AttributeSet, Theme)} that
|
||||
* accepts an override density.
|
||||
*/
|
||||
@NonNull
|
||||
static Drawable createFromXmlInnerForDensity(@NonNull Resources r,
|
||||
@NonNull XmlPullParser parser, @NonNull AttributeSet attrs, int density,
|
||||
@Nullable Theme theme) throws XmlPullParserException, IOException {
|
||||
return r.getDrawableInflater().inflateFromXmlForDensity(parser.getName(), parser, attrs,
|
||||
density, theme);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a drawable from file path name.
|
||||
*/
|
||||
@Nullable
|
||||
public static Drawable createFromPath(String pathName) {
|
||||
if (pathName == null) {
|
||||
return null;
|
||||
@@ -1315,6 +1360,16 @@ public abstract class Drawable {
|
||||
mVisible = attrs.getBoolean(visibleAttr, mVisible);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the source override density for this Drawable. If non-zero, this density is to be used
|
||||
* for any calls to {@link Resources#getDrawableForDensity(int, int, Theme)} or
|
||||
* {@link Resources#getValueForDensity(int, int, TypedValue, boolean)}.
|
||||
* @hide
|
||||
*/
|
||||
final void setSrcDensityOverride(int density) {
|
||||
mSrcDensityOverride = density;
|
||||
}
|
||||
|
||||
/**
|
||||
* This abstract class is used by {@link Drawable}s to store shared constant state and data
|
||||
* between Drawables. {@link BitmapDrawable}s created from the same resource will for instance
|
||||
|
||||
@@ -112,6 +112,17 @@ public final class DrawableInflater {
|
||||
public Drawable inflateFromXml(@NonNull String name, @NonNull XmlPullParser parser,
|
||||
@NonNull AttributeSet attrs, @Nullable Theme theme)
|
||||
throws XmlPullParserException, IOException {
|
||||
return inflateFromXmlForDensity(name, parser, attrs, 0, theme);
|
||||
}
|
||||
|
||||
/**
|
||||
* Version of {@link #inflateFromXml(String, XmlPullParser, AttributeSet, Theme)} that accepts
|
||||
* an override density.
|
||||
*/
|
||||
@NonNull
|
||||
Drawable inflateFromXmlForDensity(@NonNull String name, @NonNull XmlPullParser parser,
|
||||
@NonNull AttributeSet attrs, int density, @Nullable Theme theme)
|
||||
throws XmlPullParserException, IOException {
|
||||
// Inner classes must be referenced as Outer$Inner, but XML tag names
|
||||
// can't contain $, so the <drawable> tag allows developers to specify
|
||||
// the class in an attribute. We'll still run it through inflateFromTag
|
||||
@@ -127,6 +138,7 @@ public final class DrawableInflater {
|
||||
if (drawable == null) {
|
||||
drawable = inflateFromClass(name);
|
||||
}
|
||||
drawable.setSrcDensityOverride(density);
|
||||
drawable.inflate(mRes, parser, attrs, theme);
|
||||
return drawable;
|
||||
}
|
||||
|
||||
@@ -131,6 +131,7 @@ public abstract class DrawableWrapper extends Drawable implements Drawable.Callb
|
||||
final int densityDpi = r.getDisplayMetrics().densityDpi;
|
||||
final int targetDensity = densityDpi == 0 ? DisplayMetrics.DENSITY_DEFAULT : densityDpi;
|
||||
state.setDensity(targetDensity);
|
||||
state.mSrcDensityOverride = mSrcDensityOverride;
|
||||
|
||||
final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.DrawableWrapper);
|
||||
updateStateFromTypedArray(a);
|
||||
@@ -437,7 +438,8 @@ public abstract class DrawableWrapper extends Drawable implements Drawable.Callb
|
||||
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
|
||||
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
|
||||
if (type == XmlPullParser.START_TAG) {
|
||||
dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
|
||||
dr = Drawable.createFromXmlInnerForDensity(r, parser, attrs,
|
||||
mState.mSrcDensityOverride, theme);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -452,6 +454,14 @@ public abstract class DrawableWrapper extends Drawable implements Drawable.Callb
|
||||
@Config int mChangingConfigurations;
|
||||
int mDensity = DisplayMetrics.DENSITY_DEFAULT;
|
||||
|
||||
/**
|
||||
* The density to use when looking up resources from
|
||||
* {@link Resources#getDrawableForDensity(int, int, Theme)}.
|
||||
* A value of 0 means there is no override and the system density will be used.
|
||||
* @hide
|
||||
*/
|
||||
int mSrcDensityOverride = 0;
|
||||
|
||||
Drawable.ConstantState mDrawableState;
|
||||
|
||||
DrawableWrapperState(@Nullable DrawableWrapperState orig, @Nullable Resources res) {
|
||||
@@ -459,6 +469,7 @@ public abstract class DrawableWrapper extends Drawable implements Drawable.Callb
|
||||
mThemeAttrs = orig.mThemeAttrs;
|
||||
mChangingConfigurations = orig.mChangingConfigurations;
|
||||
mDrawableState = orig.mDrawableState;
|
||||
mSrcDensityOverride = orig.mSrcDensityOverride;
|
||||
}
|
||||
|
||||
final int density;
|
||||
|
||||
Reference in New Issue
Block a user