am 07a08010: am 425b1dc8: Merge "Add theme and config change support to more Drawable types" into lmp-mr1-dev
* commit '07a08010a87daec2091b643a8fcf2f7a27588098': Add theme and config change support to more Drawable types
This commit is contained in:
@@ -16,6 +16,8 @@
|
||||
|
||||
package android.graphics.drawable;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.ColorFilter;
|
||||
@@ -41,6 +43,7 @@ import com.android.internal.R;
|
||||
*/
|
||||
public class AnimatedRotateDrawable extends Drawable implements Drawable.Callback, Runnable,
|
||||
Animatable {
|
||||
private static final String TAG = "AnimatedRotateDrawable";
|
||||
|
||||
private AnimatedRotateState mState;
|
||||
private boolean mMutated;
|
||||
@@ -185,6 +188,11 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac
|
||||
return mState.mDrawable.getOpacity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canApplyTheme() {
|
||||
return (mState != null && mState.canApplyTheme()) || super.canApplyTheme();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateDrawable(Drawable who) {
|
||||
final Callback callback = getCallback();
|
||||
@@ -254,67 +262,21 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
|
||||
public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser,
|
||||
@NonNull AttributeSet attrs, @Nullable Theme theme)
|
||||
throws XmlPullParserException, IOException {
|
||||
|
||||
final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.AnimatedRotateDrawable);
|
||||
|
||||
super.inflateWithAttributes(r, parser, a, R.styleable.AnimatedRotateDrawable_visible);
|
||||
|
||||
TypedValue tv = a.peekValue(R.styleable.AnimatedRotateDrawable_pivotX);
|
||||
final boolean pivotXRel = tv.type == TypedValue.TYPE_FRACTION;
|
||||
final float pivotX = pivotXRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
|
||||
|
||||
tv = a.peekValue(R.styleable.AnimatedRotateDrawable_pivotY);
|
||||
final boolean pivotYRel = tv.type == TypedValue.TYPE_FRACTION;
|
||||
final float pivotY = pivotYRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
|
||||
|
||||
setFramesCount(a.getInt(R.styleable.AnimatedRotateDrawable_framesCount, 12));
|
||||
setFramesDuration(a.getInt(R.styleable.AnimatedRotateDrawable_frameDuration, 150));
|
||||
|
||||
final int res = a.getResourceId(R.styleable.AnimatedRotateDrawable_drawable, 0);
|
||||
Drawable drawable = null;
|
||||
if (res > 0) {
|
||||
drawable = r.getDrawable(res, theme);
|
||||
}
|
||||
|
||||
updateStateFromTypedArray(a);
|
||||
a.recycle();
|
||||
|
||||
int outerDepth = parser.getDepth();
|
||||
int type;
|
||||
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT &&
|
||||
(type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
|
||||
|
||||
if (type != XmlPullParser.START_TAG) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((drawable = Drawable.createFromXmlInner(r, parser, attrs, theme)) == null) {
|
||||
Log.w("drawable", "Bad element under <animated-rotate>: "
|
||||
+ parser .getName());
|
||||
}
|
||||
}
|
||||
|
||||
if (drawable == null) {
|
||||
Log.w("drawable", "No drawable specified for <animated-rotate>");
|
||||
}
|
||||
|
||||
final AnimatedRotateState rotateState = mState;
|
||||
rotateState.mDrawable = drawable;
|
||||
rotateState.mPivotXRel = pivotXRel;
|
||||
rotateState.mPivotX = pivotX;
|
||||
rotateState.mPivotYRel = pivotYRel;
|
||||
rotateState.mPivotY = pivotY;
|
||||
inflateChildElements(r, parser, attrs, theme);
|
||||
|
||||
init();
|
||||
|
||||
if (drawable != null) {
|
||||
drawable.setCallback(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyTheme(Theme t) {
|
||||
public void applyTheme(@Nullable Theme t) {
|
||||
super.applyTheme(t);
|
||||
|
||||
final AnimatedRotateState state = mState;
|
||||
@@ -322,15 +284,91 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac
|
||||
return;
|
||||
}
|
||||
|
||||
if (state.mDrawable != null) {
|
||||
if (state.mThemeAttrs != null) {
|
||||
final TypedArray a = t.resolveAttributes(
|
||||
state.mThemeAttrs, R.styleable.AnimatedRotateDrawable);
|
||||
try {
|
||||
updateStateFromTypedArray(a);
|
||||
verifyRequiredAttributes(a);
|
||||
} catch (XmlPullParserException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
a.recycle();
|
||||
}
|
||||
}
|
||||
|
||||
if (state.mDrawable != null && state.mDrawable.canApplyTheme()) {
|
||||
state.mDrawable.applyTheme(t);
|
||||
}
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
private void updateStateFromTypedArray(TypedArray a) {
|
||||
final AnimatedRotateState state = mState;
|
||||
|
||||
// Account for any configuration changes.
|
||||
state.mChangingConfigurations |= a.getChangingConfigurations();
|
||||
|
||||
// Extract the theme attributes, if any.
|
||||
state.mThemeAttrs = a.extractThemeAttrs();
|
||||
|
||||
if (a.hasValue(R.styleable.AnimatedRotateDrawable_pivotX)) {
|
||||
final TypedValue tv = a.peekValue(R.styleable.AnimatedRotateDrawable_pivotX);
|
||||
state.mPivotXRel = tv.type == TypedValue.TYPE_FRACTION;
|
||||
state.mPivotX = state.mPivotXRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
|
||||
}
|
||||
|
||||
if (a.hasValue(R.styleable.AnimatedRotateDrawable_pivotY)) {
|
||||
final TypedValue tv = a.peekValue(R.styleable.AnimatedRotateDrawable_pivotY);
|
||||
state.mPivotYRel = tv.type == TypedValue.TYPE_FRACTION;
|
||||
state.mPivotY = state.mPivotYRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
|
||||
}
|
||||
|
||||
setFramesCount(a.getInt(
|
||||
R.styleable.AnimatedRotateDrawable_framesCount, state.mFramesCount));
|
||||
setFramesDuration(a.getInt(
|
||||
R.styleable.AnimatedRotateDrawable_frameDuration, state.mFrameDuration));
|
||||
|
||||
final Drawable dr = a.getDrawable(R.styleable.AnimatedRotateDrawable_drawable);
|
||||
if (dr != null) {
|
||||
state.mDrawable = dr;
|
||||
dr.setCallback(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canApplyTheme() {
|
||||
private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
|
||||
Theme theme) throws XmlPullParserException, IOException {
|
||||
final AnimatedRotateState state = mState;
|
||||
return state != null && state.mDrawable != null && state.mDrawable.canApplyTheme();
|
||||
|
||||
Drawable dr = null;
|
||||
int outerDepth = parser.getDepth();
|
||||
int type;
|
||||
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
|
||||
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
|
||||
if (type != XmlPullParser.START_TAG) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((dr = Drawable.createFromXmlInner(r, parser, attrs, theme)) == null) {
|
||||
Log.w(TAG, "Bad element under <animated-rotate>: " + parser.getName());
|
||||
}
|
||||
}
|
||||
|
||||
if (dr != null) {
|
||||
state.mDrawable = dr;
|
||||
dr.setCallback(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException {
|
||||
// If we're not waiting on a theme, verify required attributes.
|
||||
if (mState.mDrawable == null && (mState.mThemeAttrs == null
|
||||
|| mState.mThemeAttrs[R.styleable.AnimatedRotateDrawable_drawable] == 0)) {
|
||||
throw new XmlPullParserException(a.getPositionDescription()
|
||||
+ ": <animated-rotate> tag requires a 'drawable' attribute or "
|
||||
+ "child tag defining a drawable");
|
||||
}
|
||||
}
|
||||
|
||||
public void setFramesCount(int framesCount) {
|
||||
@@ -362,15 +400,16 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac
|
||||
|
||||
final static class AnimatedRotateState extends Drawable.ConstantState {
|
||||
Drawable mDrawable;
|
||||
int[] mThemeAttrs;
|
||||
|
||||
int mChangingConfigurations;
|
||||
|
||||
boolean mPivotXRel;
|
||||
float mPivotX;
|
||||
boolean mPivotYRel;
|
||||
float mPivotY;
|
||||
int mFrameDuration;
|
||||
int mFramesCount;
|
||||
boolean mPivotXRel = false;
|
||||
float mPivotX = 0;
|
||||
boolean mPivotYRel = false;
|
||||
float mPivotY = 0;
|
||||
int mFrameDuration = 150;
|
||||
int mFramesCount = 12;
|
||||
|
||||
private boolean mCanConstantState;
|
||||
private boolean mCheckedConstantState;
|
||||
@@ -387,6 +426,7 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac
|
||||
mDrawable.setLayoutDirection(orig.mDrawable.getLayoutDirection());
|
||||
mDrawable.setBounds(orig.mDrawable.getBounds());
|
||||
mDrawable.setLevel(orig.mDrawable.getLevel());
|
||||
mThemeAttrs = orig.mThemeAttrs;
|
||||
mPivotXRel = orig.mPivotXRel;
|
||||
mPivotX = orig.mPivotX;
|
||||
mPivotYRel = orig.mPivotYRel;
|
||||
@@ -407,6 +447,12 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac
|
||||
return new AnimatedRotateDrawable(this, res);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canApplyTheme() {
|
||||
return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme())
|
||||
|| super.canApplyTheme();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChangingConfigurations() {
|
||||
return mChangingConfigurations;
|
||||
|
||||
@@ -347,24 +347,62 @@ public class AnimatedStateListDrawable extends StateListDrawable {
|
||||
throws XmlPullParserException, IOException {
|
||||
final TypedArray a = obtainAttributes(
|
||||
r, theme, attrs, R.styleable.AnimatedStateListDrawable);
|
||||
|
||||
super.inflateWithAttributes(r, parser, a, R.styleable.AnimatedStateListDrawable_visible);
|
||||
|
||||
final StateListState stateListState = getStateListState();
|
||||
stateListState.setVariablePadding(a.getBoolean(
|
||||
R.styleable.AnimatedStateListDrawable_variablePadding, false));
|
||||
stateListState.setConstantSize(a.getBoolean(
|
||||
R.styleable.AnimatedStateListDrawable_constantSize, false));
|
||||
stateListState.setEnterFadeDuration(a.getInt(
|
||||
R.styleable.AnimatedStateListDrawable_enterFadeDuration, 0));
|
||||
stateListState.setExitFadeDuration(a.getInt(
|
||||
R.styleable.AnimatedStateListDrawable_exitFadeDuration, 0));
|
||||
|
||||
setDither(a.getBoolean(R.styleable.AnimatedStateListDrawable_dither, true));
|
||||
setAutoMirrored(a.getBoolean(R.styleable.AnimatedStateListDrawable_autoMirrored, false));
|
||||
|
||||
updateStateFromTypedArray(a);
|
||||
a.recycle();
|
||||
|
||||
inflateChildElements(r, parser, attrs, theme);
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyTheme(@Nullable Theme theme) {
|
||||
super.applyTheme(theme);
|
||||
|
||||
final AnimatedStateListState state = mState;
|
||||
if (state == null || !state.canApplyTheme()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final TypedArray a = theme.resolveAttributes(
|
||||
state.mAnimThemeAttrs, R.styleable.AnimatedRotateDrawable);
|
||||
updateStateFromTypedArray(a);
|
||||
a.recycle();
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
private void updateStateFromTypedArray(TypedArray a) {
|
||||
final AnimatedStateListState state = mState;
|
||||
|
||||
// Account for any configuration changes.
|
||||
state.mChangingConfigurations |= a.getChangingConfigurations();
|
||||
|
||||
// Extract the theme attributes, if any.
|
||||
state.mAnimThemeAttrs = a.extractThemeAttrs();
|
||||
|
||||
state.setVariablePadding(a.getBoolean(
|
||||
R.styleable.AnimatedStateListDrawable_variablePadding, state.mVariablePadding));
|
||||
state.setConstantSize(a.getBoolean(
|
||||
R.styleable.AnimatedStateListDrawable_constantSize, state.mConstantSize));
|
||||
state.setEnterFadeDuration(a.getInt(
|
||||
R.styleable.AnimatedStateListDrawable_enterFadeDuration, state.mEnterFadeDuration));
|
||||
state.setExitFadeDuration(a.getInt(
|
||||
R.styleable.AnimatedStateListDrawable_exitFadeDuration, state.mExitFadeDuration));
|
||||
|
||||
setDither(a.getBoolean(
|
||||
R.styleable.AnimatedStateListDrawable_dither, state.mDither));
|
||||
setAutoMirrored(a.getBoolean(
|
||||
R.styleable.AnimatedStateListDrawable_autoMirrored, state.mAutoMirrored));
|
||||
}
|
||||
|
||||
private void init() {
|
||||
onStateChange(getState());
|
||||
}
|
||||
|
||||
private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
|
||||
Theme theme) throws XmlPullParserException, IOException {
|
||||
int type;
|
||||
|
||||
final int innerDepth = parser.getDepth() + 1;
|
||||
@@ -386,8 +424,6 @@ public class AnimatedStateListDrawable extends StateListDrawable {
|
||||
parseTransition(r, parser, attrs, theme);
|
||||
}
|
||||
}
|
||||
|
||||
onStateChange(getState());
|
||||
}
|
||||
|
||||
private int parseTransition(@NonNull Resources r, @NonNull XmlPullParser parser,
|
||||
@@ -507,6 +543,8 @@ public class AnimatedStateListDrawable extends StateListDrawable {
|
||||
private static final int REVERSE_SHIFT = 32;
|
||||
private static final int REVERSE_MASK = 0x1;
|
||||
|
||||
int[] mAnimThemeAttrs;
|
||||
|
||||
final LongSparseLongArray mTransitions;
|
||||
final SparseIntArray mStateIds;
|
||||
|
||||
@@ -515,6 +553,7 @@ public class AnimatedStateListDrawable extends StateListDrawable {
|
||||
super(orig, owner, res);
|
||||
|
||||
if (orig != null) {
|
||||
mAnimThemeAttrs = orig.mAnimThemeAttrs;
|
||||
mTransitions = orig.mTransitions.clone();
|
||||
mStateIds = orig.mStateIds.clone();
|
||||
} else {
|
||||
@@ -565,6 +604,11 @@ public class AnimatedStateListDrawable extends StateListDrawable {
|
||||
return (mTransitions.get(keyFromTo, -1) >> REVERSE_SHIFT & REVERSE_MASK) == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canApplyTheme() {
|
||||
return mAnimThemeAttrs != null || super.canApplyTheme();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable newDrawable() {
|
||||
return new AnimatedStateListDrawable(this, null);
|
||||
|
||||
@@ -316,9 +316,8 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable {
|
||||
|
||||
@Override
|
||||
public boolean canApplyTheme() {
|
||||
return super.canApplyTheme() || mAnimatedVectorState != null
|
||||
&& mAnimatedVectorState.mVectorDrawable != null
|
||||
&& mAnimatedVectorState.mVectorDrawable.canApplyTheme();
|
||||
return (mAnimatedVectorState != null && mAnimatedVectorState.canApplyTheme())
|
||||
|| super.canApplyTheme();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -373,6 +372,12 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canApplyTheme() {
|
||||
return (mVectorDrawable != null && mVectorDrawable.canApplyTheme())
|
||||
|| super.canApplyTheme();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable newDrawable() {
|
||||
return new AnimatedVectorDrawable(this, null);
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package android.graphics.drawable;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
@@ -271,27 +273,25 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An
|
||||
@Override
|
||||
public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
|
||||
throws XmlPullParserException, IOException {
|
||||
|
||||
TypedArray a = obtainAttributes(r, theme, attrs,
|
||||
com.android.internal.R.styleable.AnimationDrawable);
|
||||
|
||||
super.inflateWithAttributes(r, parser, a,
|
||||
com.android.internal.R.styleable.AnimationDrawable_visible);
|
||||
|
||||
mAnimationState.setVariablePadding(a.getBoolean(
|
||||
com.android.internal.R.styleable.AnimationDrawable_variablePadding, false));
|
||||
|
||||
mAnimationState.mOneShot = a.getBoolean(
|
||||
com.android.internal.R.styleable.AnimationDrawable_oneshot, false);
|
||||
|
||||
final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.AnimationDrawable);
|
||||
super.inflateWithAttributes(r, parser, a, R.styleable.AnimationDrawable_visible);
|
||||
updateStateFromTypedArray(a);
|
||||
a.recycle();
|
||||
|
||||
inflateChildElements(r, parser, attrs, theme);
|
||||
|
||||
setFrame(0, true, false);
|
||||
}
|
||||
|
||||
private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
|
||||
Theme theme) throws XmlPullParserException, IOException {
|
||||
TypedArray a;
|
||||
int type;
|
||||
|
||||
final int innerDepth = parser.getDepth()+1;
|
||||
int depth;
|
||||
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT &&
|
||||
((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
|
||||
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
|
||||
&& ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
|
||||
if (type != XmlPullParser.START_TAG) {
|
||||
continue;
|
||||
}
|
||||
@@ -300,17 +300,15 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An
|
||||
continue;
|
||||
}
|
||||
|
||||
a = obtainAttributes(
|
||||
r, theme, attrs, com.android.internal.R.styleable.AnimationDrawableItem);
|
||||
int duration = a.getInt(
|
||||
com.android.internal.R.styleable.AnimationDrawableItem_duration, -1);
|
||||
a = obtainAttributes(r, theme, attrs, R.styleable.AnimationDrawableItem);
|
||||
|
||||
final int duration = a.getInt(R.styleable.AnimationDrawableItem_duration, -1);
|
||||
if (duration < 0) {
|
||||
throw new XmlPullParserException(
|
||||
parser.getPositionDescription()
|
||||
throw new XmlPullParserException(parser.getPositionDescription()
|
||||
+ ": <item> tag requires a 'duration' attribute");
|
||||
}
|
||||
int drawableRes = a.getResourceId(
|
||||
com.android.internal.R.styleable.AnimationDrawableItem_drawable, 0);
|
||||
|
||||
final int drawableRes = a.getResourceId(R.styleable.AnimationDrawableItem_drawable, 0);
|
||||
|
||||
a.recycle();
|
||||
|
||||
@@ -322,9 +320,9 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An
|
||||
// Empty
|
||||
}
|
||||
if (type != XmlPullParser.START_TAG) {
|
||||
throw new XmlPullParserException(parser.getPositionDescription() +
|
||||
": <item> tag requires a 'drawable' attribute or child tag" +
|
||||
" defining a drawable");
|
||||
throw new XmlPullParserException(parser.getPositionDescription()
|
||||
+ ": <item> tag requires a 'drawable' attribute or child tag"
|
||||
+ " defining a drawable");
|
||||
}
|
||||
dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
|
||||
}
|
||||
@@ -334,8 +332,14 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An
|
||||
dr.setCallback(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setFrame(0, true, false);
|
||||
private void updateStateFromTypedArray(TypedArray a) {
|
||||
mAnimationState.mVariablePadding = a.getBoolean(
|
||||
R.styleable.AnimationDrawable_variablePadding, mAnimationState.mVariablePadding);
|
||||
|
||||
mAnimationState.mOneShot = a.getBoolean(
|
||||
R.styleable.AnimationDrawable_oneshot, mAnimationState.mOneShot);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -357,7 +361,7 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An
|
||||
|
||||
private final static class AnimationState extends DrawableContainerState {
|
||||
private int[] mDurations;
|
||||
private boolean mOneShot;
|
||||
private boolean mOneShot = false;
|
||||
|
||||
AnimationState(AnimationState orig, AnimationDrawable owner,
|
||||
Resources res) {
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package android.graphics.drawable;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
@@ -49,7 +51,7 @@ import java.io.IOException;
|
||||
* @attr ref android.R.styleable#ClipDrawable_drawable
|
||||
*/
|
||||
public class ClipDrawable extends Drawable implements Drawable.Callback {
|
||||
private ClipState mClipState;
|
||||
private ClipState mState;
|
||||
private final Rect mTmpRect = new Rect();
|
||||
|
||||
public static final int HORIZONTAL = 1;
|
||||
@@ -67,9 +69,9 @@ public class ClipDrawable extends Drawable implements Drawable.Callback {
|
||||
public ClipDrawable(Drawable drawable, int gravity, int orientation) {
|
||||
this(null, null);
|
||||
|
||||
mClipState.mDrawable = drawable;
|
||||
mClipState.mGravity = gravity;
|
||||
mClipState.mOrientation = orientation;
|
||||
mState.mDrawable = drawable;
|
||||
mState.mGravity = gravity;
|
||||
mState.mOrientation = orientation;
|
||||
|
||||
if (drawable != null) {
|
||||
drawable.setCallback(this);
|
||||
@@ -81,19 +83,22 @@ public class ClipDrawable extends Drawable implements Drawable.Callback {
|
||||
throws XmlPullParserException, IOException {
|
||||
super.inflate(r, parser, attrs, theme);
|
||||
|
||||
int type;
|
||||
final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.ClipDrawable);
|
||||
|
||||
TypedArray a = obtainAttributes(
|
||||
r, theme, attrs, com.android.internal.R.styleable.ClipDrawable);
|
||||
|
||||
int orientation = a.getInt(
|
||||
com.android.internal.R.styleable.ClipDrawable_clipOrientation,
|
||||
HORIZONTAL);
|
||||
int g = a.getInt(com.android.internal.R.styleable.ClipDrawable_gravity, Gravity.LEFT);
|
||||
Drawable dr = a.getDrawable(com.android.internal.R.styleable.ClipDrawable_drawable);
|
||||
// Reset mDrawable to preserve old multiple-inflate behavior. This is
|
||||
// silly, but we have CTS tests that rely on it.
|
||||
mState.mDrawable = null;
|
||||
|
||||
updateStateFromTypedArray(a);
|
||||
inflateChildElements(r, parser, attrs, theme);
|
||||
verifyRequiredAttributes(a);
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
|
||||
Theme theme) throws XmlPullParserException, IOException {
|
||||
Drawable dr = null;
|
||||
int type;
|
||||
final int outerDepth = parser.getDepth();
|
||||
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
|
||||
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
|
||||
@@ -103,35 +108,68 @@ public class ClipDrawable extends Drawable implements Drawable.Callback {
|
||||
dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
|
||||
}
|
||||
|
||||
if (dr == null) {
|
||||
throw new IllegalArgumentException("No drawable specified for <clip>");
|
||||
if (dr != null) {
|
||||
mState.mDrawable = dr;
|
||||
dr.setCallback(this);
|
||||
}
|
||||
}
|
||||
|
||||
mClipState.mDrawable = dr;
|
||||
mClipState.mOrientation = orientation;
|
||||
mClipState.mGravity = g;
|
||||
private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException {
|
||||
// If we're not waiting on a theme, verify required attributes.
|
||||
if (mState.mDrawable == null && (mState.mThemeAttrs == null
|
||||
|| mState.mThemeAttrs[R.styleable.ClipDrawable_drawable] == 0)) {
|
||||
throw new XmlPullParserException(a.getPositionDescription()
|
||||
+ ": <clip> tag requires a 'drawable' attribute or "
|
||||
+ "child tag defining a drawable");
|
||||
}
|
||||
}
|
||||
|
||||
dr.setCallback(this);
|
||||
private void updateStateFromTypedArray(TypedArray a) {
|
||||
final ClipState state = mState;
|
||||
|
||||
// Account for any configuration changes.
|
||||
state.mChangingConfigurations |= a.getChangingConfigurations();
|
||||
|
||||
// Extract the theme attributes, if any.
|
||||
state.mThemeAttrs = a.extractThemeAttrs();
|
||||
|
||||
state.mOrientation = a.getInt(R.styleable.ClipDrawable_clipOrientation, state.mOrientation);
|
||||
state.mGravity = a.getInt(R.styleable.ClipDrawable_gravity, state.mGravity);
|
||||
|
||||
final Drawable dr = a.getDrawable(R.styleable.ClipDrawable_drawable);
|
||||
if (dr != null) {
|
||||
state.mDrawable = dr;
|
||||
dr.setCallback(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyTheme(Theme t) {
|
||||
super.applyTheme(t);
|
||||
|
||||
final ClipState state = mClipState;
|
||||
final ClipState state = mState;
|
||||
if (state == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (state.mDrawable != null) {
|
||||
final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.ClipDrawable);
|
||||
try {
|
||||
updateStateFromTypedArray(a);
|
||||
verifyRequiredAttributes(a);
|
||||
} catch (XmlPullParserException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
if (state.mDrawable != null && state.mDrawable.canApplyTheme()) {
|
||||
state.mDrawable.applyTheme(t);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canApplyTheme() {
|
||||
final ClipState state = mClipState;
|
||||
return state != null && state.mDrawable != null && state.mDrawable.canApplyTheme();
|
||||
return (mState != null && mState.canApplyTheme()) || super.canApplyTheme();
|
||||
}
|
||||
|
||||
// overrides from Drawable.Callback
|
||||
@@ -165,78 +203,78 @@ public class ClipDrawable extends Drawable implements Drawable.Callback {
|
||||
@Override
|
||||
public int getChangingConfigurations() {
|
||||
return super.getChangingConfigurations()
|
||||
| mClipState.mChangingConfigurations
|
||||
| mClipState.mDrawable.getChangingConfigurations();
|
||||
| mState.mChangingConfigurations
|
||||
| mState.mDrawable.getChangingConfigurations();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getPadding(Rect padding) {
|
||||
// XXX need to adjust padding!
|
||||
return mClipState.mDrawable.getPadding(padding);
|
||||
return mState.mDrawable.getPadding(padding);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setVisible(boolean visible, boolean restart) {
|
||||
mClipState.mDrawable.setVisible(visible, restart);
|
||||
mState.mDrawable.setVisible(visible, restart);
|
||||
return super.setVisible(visible, restart);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
mClipState.mDrawable.setAlpha(alpha);
|
||||
mState.mDrawable.setAlpha(alpha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAlpha() {
|
||||
return mClipState.mDrawable.getAlpha();
|
||||
return mState.mDrawable.getAlpha();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(ColorFilter cf) {
|
||||
mClipState.mDrawable.setColorFilter(cf);
|
||||
mState.mDrawable.setColorFilter(cf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTintList(ColorStateList tint) {
|
||||
mClipState.mDrawable.setTintList(tint);
|
||||
mState.mDrawable.setTintList(tint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTintMode(Mode tintMode) {
|
||||
mClipState.mDrawable.setTintMode(tintMode);
|
||||
mState.mDrawable.setTintMode(tintMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
return mClipState.mDrawable.getOpacity();
|
||||
return mState.mDrawable.getOpacity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStateful() {
|
||||
return mClipState.mDrawable.isStateful();
|
||||
return mState.mDrawable.isStateful();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onStateChange(int[] state) {
|
||||
return mClipState.mDrawable.setState(state);
|
||||
return mState.mDrawable.setState(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onLevelChange(int level) {
|
||||
mClipState.mDrawable.setLevel(level);
|
||||
mState.mDrawable.setLevel(level);
|
||||
invalidateSelf();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBoundsChange(Rect bounds) {
|
||||
mClipState.mDrawable.setBounds(bounds);
|
||||
mState.mDrawable.setBounds(bounds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
|
||||
if (mClipState.mDrawable.getLevel() == 0) {
|
||||
if (mState.mDrawable.getLevel() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -244,41 +282,41 @@ public class ClipDrawable extends Drawable implements Drawable.Callback {
|
||||
final Rect bounds = getBounds();
|
||||
int level = getLevel();
|
||||
int w = bounds.width();
|
||||
final int iw = 0; //mClipState.mDrawable.getIntrinsicWidth();
|
||||
if ((mClipState.mOrientation & HORIZONTAL) != 0) {
|
||||
final int iw = 0; //mState.mDrawable.getIntrinsicWidth();
|
||||
if ((mState.mOrientation & HORIZONTAL) != 0) {
|
||||
w -= (w - iw) * (10000 - level) / 10000;
|
||||
}
|
||||
int h = bounds.height();
|
||||
final int ih = 0; //mClipState.mDrawable.getIntrinsicHeight();
|
||||
if ((mClipState.mOrientation & VERTICAL) != 0) {
|
||||
final int ih = 0; //mState.mDrawable.getIntrinsicHeight();
|
||||
if ((mState.mOrientation & VERTICAL) != 0) {
|
||||
h -= (h - ih) * (10000 - level) / 10000;
|
||||
}
|
||||
final int layoutDirection = getLayoutDirection();
|
||||
Gravity.apply(mClipState.mGravity, w, h, bounds, r, layoutDirection);
|
||||
Gravity.apply(mState.mGravity, w, h, bounds, r, layoutDirection);
|
||||
|
||||
if (w > 0 && h > 0) {
|
||||
canvas.save();
|
||||
canvas.clipRect(r);
|
||||
mClipState.mDrawable.draw(canvas);
|
||||
mState.mDrawable.draw(canvas);
|
||||
canvas.restore();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicWidth() {
|
||||
return mClipState.mDrawable.getIntrinsicWidth();
|
||||
return mState.mDrawable.getIntrinsicWidth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicHeight() {
|
||||
return mClipState.mDrawable.getIntrinsicHeight();
|
||||
return mState.mDrawable.getIntrinsicHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConstantState getConstantState() {
|
||||
if (mClipState.canConstantState()) {
|
||||
mClipState.mChangingConfigurations = getChangingConfigurations();
|
||||
return mClipState;
|
||||
if (mState.canConstantState()) {
|
||||
mState.mChangingConfigurations = getChangingConfigurations();
|
||||
return mState;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -286,14 +324,14 @@ public class ClipDrawable extends Drawable implements Drawable.Callback {
|
||||
/** @hide */
|
||||
@Override
|
||||
public void setLayoutDirection(int layoutDirection) {
|
||||
mClipState.mDrawable.setLayoutDirection(layoutDirection);
|
||||
mState.mDrawable.setLayoutDirection(layoutDirection);
|
||||
super.setLayoutDirection(layoutDirection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable mutate() {
|
||||
if (!mMutated && super.mutate() == this) {
|
||||
mClipState.mDrawable.mutate();
|
||||
mState.mDrawable.mutate();
|
||||
mMutated = true;
|
||||
}
|
||||
return this;
|
||||
@@ -304,21 +342,26 @@ public class ClipDrawable extends Drawable implements Drawable.Callback {
|
||||
*/
|
||||
public void clearMutated() {
|
||||
super.clearMutated();
|
||||
mClipState.mDrawable.clearMutated();
|
||||
mState.mDrawable.clearMutated();
|
||||
mMutated = false;
|
||||
}
|
||||
|
||||
final static class ClipState extends ConstantState {
|
||||
Drawable mDrawable;
|
||||
int[] mThemeAttrs;
|
||||
int mChangingConfigurations;
|
||||
int mOrientation;
|
||||
int mGravity;
|
||||
|
||||
Drawable mDrawable;
|
||||
|
||||
int mOrientation = HORIZONTAL;
|
||||
int mGravity = Gravity.LEFT;
|
||||
|
||||
private boolean mCheckedConstantState;
|
||||
private boolean mCanConstantState;
|
||||
|
||||
ClipState(ClipState orig, ClipDrawable owner, Resources res) {
|
||||
if (orig != null) {
|
||||
mThemeAttrs = orig.mThemeAttrs;
|
||||
mChangingConfigurations = orig.mChangingConfigurations;
|
||||
if (res != null) {
|
||||
mDrawable = orig.mDrawable.getConstantState().newDrawable(res);
|
||||
} else {
|
||||
@@ -334,6 +377,12 @@ public class ClipDrawable extends Drawable implements Drawable.Callback {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canApplyTheme() {
|
||||
return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme())
|
||||
|| super.canApplyTheme();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable newDrawable() {
|
||||
return new ClipDrawable(this, null);
|
||||
@@ -360,7 +409,7 @@ public class ClipDrawable extends Drawable implements Drawable.Callback {
|
||||
}
|
||||
|
||||
private ClipDrawable(ClipState state, Resources res) {
|
||||
mClipState = new ClipState(state, this, res);
|
||||
mState = new ClipState(state, this, res);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -600,11 +600,11 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
|
||||
Drawable[] mDrawables;
|
||||
int mNumChildren;
|
||||
|
||||
boolean mVariablePadding;
|
||||
boolean mVariablePadding = false;
|
||||
boolean mPaddingChecked;
|
||||
Rect mConstantPadding;
|
||||
|
||||
boolean mConstantSize;
|
||||
boolean mConstantSize = false;
|
||||
boolean mComputedConstantSize;
|
||||
int mConstantWidth;
|
||||
int mConstantHeight;
|
||||
@@ -625,8 +625,8 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
|
||||
boolean mMutated;
|
||||
int mLayoutDirection;
|
||||
|
||||
int mEnterFadeDuration;
|
||||
int mExitFadeDuration;
|
||||
int mEnterFadeDuration = 0;
|
||||
int mExitFadeDuration = 0;
|
||||
|
||||
boolean mAutoMirrored;
|
||||
|
||||
|
||||
@@ -1089,7 +1089,7 @@ public class GradientDrawable extends Drawable {
|
||||
|
||||
@Override
|
||||
public boolean canApplyTheme() {
|
||||
return super.canApplyTheme() || mGradientState != null && mGradientState.canApplyTheme();
|
||||
return (mGradientState != null && mGradientState.canApplyTheme()) || super.canApplyTheme();
|
||||
}
|
||||
|
||||
private void applyThemeChildElements(Theme t) {
|
||||
@@ -1632,7 +1632,7 @@ public class GradientDrawable extends Drawable {
|
||||
public boolean canApplyTheme() {
|
||||
return mThemeAttrs != null || mAttrSize != null || mAttrGradient != null
|
||||
|| mAttrSolid != null || mAttrStroke != null || mAttrCorners != null
|
||||
|| mAttrPadding != null;
|
||||
|| mAttrPadding != null || super.canApplyTheme();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -55,7 +55,8 @@ import java.io.IOException;
|
||||
public class InsetDrawable extends Drawable implements Drawable.Callback {
|
||||
private final Rect mTmpRect = new Rect();
|
||||
|
||||
private InsetState mInsetState;
|
||||
private final InsetState mState;
|
||||
|
||||
private boolean mMutated;
|
||||
|
||||
/*package*/ InsetDrawable() {
|
||||
@@ -70,11 +71,11 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
|
||||
int insetRight, int insetBottom) {
|
||||
this(null, null);
|
||||
|
||||
mInsetState.mDrawable = drawable;
|
||||
mInsetState.mInsetLeft = insetLeft;
|
||||
mInsetState.mInsetTop = insetTop;
|
||||
mInsetState.mInsetRight = insetRight;
|
||||
mInsetState.mInsetBottom = insetBottom;
|
||||
mState.mDrawable = drawable;
|
||||
mState.mInsetLeft = insetLeft;
|
||||
mState.mInsetTop = insetTop;
|
||||
mState.mInsetRight = insetRight;
|
||||
mState.mInsetBottom = insetBottom;
|
||||
|
||||
if (drawable != null) {
|
||||
drawable.setCallback(this);
|
||||
@@ -87,11 +88,20 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
|
||||
final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.InsetDrawable);
|
||||
super.inflateWithAttributes(r, parser, a, R.styleable.InsetDrawable_visible);
|
||||
|
||||
mInsetState.mDrawable = null;
|
||||
updateStateFromTypedArray(a);
|
||||
// Reset mDrawable to preserve old multiple-inflate behavior. This is
|
||||
// silly, but we have CTS tests that rely on it.
|
||||
mState.mDrawable = null;
|
||||
|
||||
updateStateFromTypedArray(a);
|
||||
inflateChildElements(r, parser, attrs, theme);
|
||||
verifyRequiredAttributes(a);
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
|
||||
Theme theme) throws XmlPullParserException, IOException {
|
||||
// Load inner XML elements.
|
||||
if (mInsetState.mDrawable == null) {
|
||||
if (mState.mDrawable == null) {
|
||||
int type;
|
||||
while ((type=parser.next()) == XmlPullParser.TEXT) {
|
||||
}
|
||||
@@ -102,26 +112,23 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
|
||||
+ "child tag defining a drawable");
|
||||
}
|
||||
final Drawable dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
|
||||
mInsetState.mDrawable = dr;
|
||||
mState.mDrawable = dr;
|
||||
dr.setCallback(this);
|
||||
}
|
||||
|
||||
verifyRequiredAttributes(a);
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException {
|
||||
// If we're not waiting on a theme, verify required attributes.
|
||||
if (mInsetState.mDrawable == null && (mInsetState.mThemeAttrs == null
|
||||
|| mInsetState.mThemeAttrs[R.styleable.InsetDrawable_drawable] == 0)) {
|
||||
throw new XmlPullParserException(a.getPositionDescription() +
|
||||
": <inset> tag requires a 'drawable' attribute or "
|
||||
if (mState.mDrawable == null && (mState.mThemeAttrs == null
|
||||
|| mState.mThemeAttrs[R.styleable.InsetDrawable_drawable] == 0)) {
|
||||
throw new XmlPullParserException(a.getPositionDescription()
|
||||
+ ": <inset> tag requires a 'drawable' attribute or "
|
||||
+ "child tag defining a drawable");
|
||||
}
|
||||
}
|
||||
|
||||
private void updateStateFromTypedArray(TypedArray a) throws XmlPullParserException {
|
||||
final InsetState state = mInsetState;
|
||||
final InsetState state = mState;
|
||||
|
||||
// Account for any configuration changes.
|
||||
state.mChangingConfigurations |= a.getChangingConfigurations();
|
||||
@@ -169,7 +176,7 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
|
||||
public void applyTheme(Theme t) {
|
||||
super.applyTheme(t);
|
||||
|
||||
final InsetState state = mInsetState;
|
||||
final InsetState state = mState;
|
||||
if (state == null) {
|
||||
return;
|
||||
}
|
||||
@@ -193,7 +200,7 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
|
||||
|
||||
@Override
|
||||
public boolean canApplyTheme() {
|
||||
return super.canApplyTheme() || mInsetState != null && mInsetState.canApplyTheme();
|
||||
return (mState != null && mState.canApplyTheme()) || super.canApplyTheme();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -222,112 +229,112 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
mInsetState.mDrawable.draw(canvas);
|
||||
mState.mDrawable.draw(canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChangingConfigurations() {
|
||||
return super.getChangingConfigurations()
|
||||
| mInsetState.mChangingConfigurations
|
||||
| mInsetState.mDrawable.getChangingConfigurations();
|
||||
| mState.mChangingConfigurations
|
||||
| mState.mDrawable.getChangingConfigurations();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getPadding(Rect padding) {
|
||||
boolean pad = mInsetState.mDrawable.getPadding(padding);
|
||||
boolean pad = mState.mDrawable.getPadding(padding);
|
||||
|
||||
padding.left += mInsetState.mInsetLeft;
|
||||
padding.right += mInsetState.mInsetRight;
|
||||
padding.top += mInsetState.mInsetTop;
|
||||
padding.bottom += mInsetState.mInsetBottom;
|
||||
padding.left += mState.mInsetLeft;
|
||||
padding.right += mState.mInsetRight;
|
||||
padding.top += mState.mInsetTop;
|
||||
padding.bottom += mState.mInsetBottom;
|
||||
|
||||
return pad || (mInsetState.mInsetLeft | mInsetState.mInsetRight |
|
||||
mInsetState.mInsetTop | mInsetState.mInsetBottom) != 0;
|
||||
return pad || (mState.mInsetLeft | mState.mInsetRight |
|
||||
mState.mInsetTop | mState.mInsetBottom) != 0;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
public Insets getOpticalInsets() {
|
||||
final Insets contentInsets = super.getOpticalInsets();
|
||||
return Insets.of(contentInsets.left + mInsetState.mInsetLeft,
|
||||
contentInsets.top + mInsetState.mInsetTop,
|
||||
contentInsets.right + mInsetState.mInsetRight,
|
||||
contentInsets.bottom + mInsetState.mInsetBottom);
|
||||
return Insets.of(contentInsets.left + mState.mInsetLeft,
|
||||
contentInsets.top + mState.mInsetTop,
|
||||
contentInsets.right + mState.mInsetRight,
|
||||
contentInsets.bottom + mState.mInsetBottom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHotspot(float x, float y) {
|
||||
mInsetState.mDrawable.setHotspot(x, y);
|
||||
mState.mDrawable.setHotspot(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHotspotBounds(int left, int top, int right, int bottom) {
|
||||
mInsetState.mDrawable.setHotspotBounds(left, top, right, bottom);
|
||||
mState.mDrawable.setHotspotBounds(left, top, right, bottom);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
public void getHotspotBounds(Rect outRect) {
|
||||
mInsetState.mDrawable.getHotspotBounds(outRect);
|
||||
mState.mDrawable.getHotspotBounds(outRect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setVisible(boolean visible, boolean restart) {
|
||||
mInsetState.mDrawable.setVisible(visible, restart);
|
||||
mState.mDrawable.setVisible(visible, restart);
|
||||
return super.setVisible(visible, restart);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
mInsetState.mDrawable.setAlpha(alpha);
|
||||
mState.mDrawable.setAlpha(alpha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAlpha() {
|
||||
return mInsetState.mDrawable.getAlpha();
|
||||
return mState.mDrawable.getAlpha();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(ColorFilter cf) {
|
||||
mInsetState.mDrawable.setColorFilter(cf);
|
||||
mState.mDrawable.setColorFilter(cf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTintList(ColorStateList tint) {
|
||||
mInsetState.mDrawable.setTintList(tint);
|
||||
mState.mDrawable.setTintList(tint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTintMode(Mode tintMode) {
|
||||
mInsetState.mDrawable.setTintMode(tintMode);
|
||||
mState.mDrawable.setTintMode(tintMode);
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
@Override
|
||||
public void setLayoutDirection(int layoutDirection) {
|
||||
mInsetState.mDrawable.setLayoutDirection(layoutDirection);
|
||||
mState.mDrawable.setLayoutDirection(layoutDirection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
return mInsetState.mDrawable.getOpacity();
|
||||
return mState.mDrawable.getOpacity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStateful() {
|
||||
return mInsetState.mDrawable.isStateful();
|
||||
return mState.mDrawable.isStateful();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onStateChange(int[] state) {
|
||||
boolean changed = mInsetState.mDrawable.setState(state);
|
||||
boolean changed = mState.mDrawable.setState(state);
|
||||
onBoundsChange(getBounds());
|
||||
return changed;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onLevelChange(int level) {
|
||||
return mInsetState.mDrawable.setLevel(level);
|
||||
return mState.mDrawable.setLevel(level);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -335,36 +342,36 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
|
||||
final Rect r = mTmpRect;
|
||||
r.set(bounds);
|
||||
|
||||
r.left += mInsetState.mInsetLeft;
|
||||
r.top += mInsetState.mInsetTop;
|
||||
r.right -= mInsetState.mInsetRight;
|
||||
r.bottom -= mInsetState.mInsetBottom;
|
||||
r.left += mState.mInsetLeft;
|
||||
r.top += mState.mInsetTop;
|
||||
r.right -= mState.mInsetRight;
|
||||
r.bottom -= mState.mInsetBottom;
|
||||
|
||||
mInsetState.mDrawable.setBounds(r.left, r.top, r.right, r.bottom);
|
||||
mState.mDrawable.setBounds(r.left, r.top, r.right, r.bottom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicWidth() {
|
||||
return mInsetState.mDrawable.getIntrinsicWidth()
|
||||
+ mInsetState.mInsetLeft + mInsetState.mInsetRight;
|
||||
return mState.mDrawable.getIntrinsicWidth()
|
||||
+ mState.mInsetLeft + mState.mInsetRight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicHeight() {
|
||||
return mInsetState.mDrawable.getIntrinsicHeight()
|
||||
+ mInsetState.mInsetTop + mInsetState.mInsetBottom;
|
||||
return mState.mDrawable.getIntrinsicHeight()
|
||||
+ mState.mInsetTop + mState.mInsetBottom;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getOutline(@NonNull Outline outline) {
|
||||
mInsetState.mDrawable.getOutline(outline);
|
||||
mState.mDrawable.getOutline(outline);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConstantState getConstantState() {
|
||||
if (mInsetState.canConstantState()) {
|
||||
mInsetState.mChangingConfigurations = getChangingConfigurations();
|
||||
return mInsetState;
|
||||
if (mState.canConstantState()) {
|
||||
mState.mChangingConfigurations = getChangingConfigurations();
|
||||
return mState;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -372,7 +379,7 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
|
||||
@Override
|
||||
public Drawable mutate() {
|
||||
if (!mMutated && super.mutate() == this) {
|
||||
mInsetState.mDrawable.mutate();
|
||||
mState.mDrawable.mutate();
|
||||
mMutated = true;
|
||||
}
|
||||
return this;
|
||||
@@ -383,7 +390,7 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
|
||||
*/
|
||||
public void clearMutated() {
|
||||
super.clearMutated();
|
||||
mInsetState.mDrawable.clearMutated();
|
||||
mState.mDrawable.clearMutated();
|
||||
mMutated = false;
|
||||
}
|
||||
|
||||
@@ -391,7 +398,7 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
|
||||
* Returns the drawable wrapped by this InsetDrawable. May be null.
|
||||
*/
|
||||
public Drawable getDrawable() {
|
||||
return mInsetState.mDrawable;
|
||||
return mState.mDrawable;
|
||||
}
|
||||
|
||||
final static class InsetState extends ConstantState {
|
||||
@@ -400,13 +407,13 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
|
||||
|
||||
Drawable mDrawable;
|
||||
|
||||
int mInsetLeft;
|
||||
int mInsetTop;
|
||||
int mInsetRight;
|
||||
int mInsetBottom;
|
||||
int mInsetLeft = 0;
|
||||
int mInsetTop = 0;
|
||||
int mInsetRight = 0;
|
||||
int mInsetBottom = 0;
|
||||
|
||||
boolean mCheckedConstantState;
|
||||
boolean mCanConstantState;
|
||||
private boolean mCheckedConstantState;
|
||||
private boolean mCanConstantState;
|
||||
|
||||
InsetState(InsetState orig, InsetDrawable owner, Resources res) {
|
||||
if (orig != null) {
|
||||
@@ -429,6 +436,12 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canApplyTheme() {
|
||||
return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme())
|
||||
|| super.canApplyTheme();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable newDrawable() {
|
||||
return new InsetDrawable(this, null);
|
||||
@@ -444,12 +457,6 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
|
||||
return mChangingConfigurations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canApplyTheme() {
|
||||
return super.canApplyTheme() || mThemeAttrs != null
|
||||
|| mDrawable != null && mDrawable.canApplyTheme();
|
||||
}
|
||||
|
||||
boolean canConstantState() {
|
||||
if (!mCheckedConstantState) {
|
||||
mCanConstantState = mDrawable.getConstantState() != null;
|
||||
@@ -461,7 +468,7 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
|
||||
}
|
||||
|
||||
private InsetDrawable(InsetState state, Resources res) {
|
||||
mInsetState = new InsetState(state, this, res);
|
||||
mState = new InsetState(state, this, res);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -275,7 +275,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
|
||||
|
||||
@Override
|
||||
public boolean canApplyTheme() {
|
||||
return super.canApplyTheme() || mLayerState != null && mLayerState.canApplyTheme();
|
||||
return (mLayerState != null && mLayerState.canApplyTheme()) || super.canApplyTheme();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1020,7 +1020,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
|
||||
|
||||
@Override
|
||||
public boolean canApplyTheme() {
|
||||
if (mThemeAttrs != null) {
|
||||
if (mThemeAttrs != null || super.canApplyTheme()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -473,7 +473,7 @@ public class RippleDrawable extends LayerDrawable {
|
||||
|
||||
@Override
|
||||
public boolean canApplyTheme() {
|
||||
return super.canApplyTheme() || mState != null && mState.canApplyTheme();
|
||||
return (mState != null && mState.canApplyTheme()) || super.canApplyTheme();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -31,7 +31,6 @@ import android.content.res.TypedArray;
|
||||
import android.content.res.Resources.Theme;
|
||||
import android.util.TypedValue;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -313,6 +312,11 @@ public class RotateDrawable extends Drawable implements Drawable.Callback {
|
||||
return mState.mPivotYRel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canApplyTheme() {
|
||||
return (mState != null && mState.canApplyTheme()) || super.canApplyTheme();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateDrawable(Drawable who) {
|
||||
final Callback callback = getCallback();
|
||||
@@ -401,80 +405,17 @@ public class RotateDrawable extends Drawable implements Drawable.Callback {
|
||||
@Override
|
||||
public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
|
||||
throws XmlPullParserException, IOException {
|
||||
final TypedArray a = obtainAttributes(r, theme, attrs,
|
||||
com.android.internal.R.styleable.RotateDrawable);
|
||||
final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.RotateDrawable);
|
||||
super.inflateWithAttributes(r, parser, a, R.styleable.RotateDrawable_visible);
|
||||
|
||||
super.inflateWithAttributes(r, parser, a,
|
||||
com.android.internal.R.styleable.RotateDrawable_visible);
|
||||
|
||||
TypedValue tv = a.peekValue(com.android.internal.R.styleable.RotateDrawable_pivotX);
|
||||
final boolean pivotXRel;
|
||||
final float pivotX;
|
||||
if (tv == null) {
|
||||
pivotXRel = true;
|
||||
pivotX = 0.5f;
|
||||
} else {
|
||||
pivotXRel = tv.type == TypedValue.TYPE_FRACTION;
|
||||
pivotX = pivotXRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
|
||||
}
|
||||
|
||||
tv = a.peekValue(com.android.internal.R.styleable.RotateDrawable_pivotY);
|
||||
final boolean pivotYRel;
|
||||
final float pivotY;
|
||||
if (tv == null) {
|
||||
pivotYRel = true;
|
||||
pivotY = 0.5f;
|
||||
} else {
|
||||
pivotYRel = tv.type == TypedValue.TYPE_FRACTION;
|
||||
pivotY = pivotYRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
|
||||
}
|
||||
|
||||
final float fromDegrees = a.getFloat(
|
||||
com.android.internal.R.styleable.RotateDrawable_fromDegrees, 0.0f);
|
||||
final float toDegrees = a.getFloat(
|
||||
com.android.internal.R.styleable.RotateDrawable_toDegrees, 360.0f);
|
||||
|
||||
final int res = a.getResourceId(
|
||||
com.android.internal.R.styleable.RotateDrawable_drawable, 0);
|
||||
Drawable drawable = null;
|
||||
if (res > 0) {
|
||||
drawable = r.getDrawable(res, theme);
|
||||
}
|
||||
// Reset mDrawable to preserve old multiple-inflate behavior. This is
|
||||
// silly, but we have CTS tests that rely on it.
|
||||
mState.mDrawable = null;
|
||||
|
||||
updateStateFromTypedArray(a);
|
||||
inflateChildElements(r, parser, attrs, theme);
|
||||
verifyRequiredAttributes(a);
|
||||
a.recycle();
|
||||
|
||||
final int outerDepth = parser.getDepth();
|
||||
int type;
|
||||
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT &&
|
||||
(type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
|
||||
|
||||
if (type != XmlPullParser.START_TAG) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((drawable = Drawable.createFromXmlInner(r, parser, attrs, theme)) == null) {
|
||||
Log.w("drawable", "Bad element under <rotate>: "
|
||||
+ parser .getName());
|
||||
}
|
||||
}
|
||||
|
||||
if (drawable == null) {
|
||||
Log.w("drawable", "No drawable specified for <rotate>");
|
||||
}
|
||||
|
||||
final RotateState st = mState;
|
||||
st.mDrawable = drawable;
|
||||
st.mPivotXRel = pivotXRel;
|
||||
st.mPivotX = pivotX;
|
||||
st.mPivotYRel = pivotYRel;
|
||||
st.mPivotY = pivotY;
|
||||
st.mFromDegrees = fromDegrees;
|
||||
st.mCurrentDegrees = fromDegrees;
|
||||
st.mToDegrees = toDegrees;
|
||||
|
||||
if (drawable != null) {
|
||||
drawable.setCallback(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -486,15 +427,79 @@ public class RotateDrawable extends Drawable implements Drawable.Callback {
|
||||
return;
|
||||
}
|
||||
|
||||
if (state.mDrawable != null) {
|
||||
final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.RotateDrawable);
|
||||
try {
|
||||
updateStateFromTypedArray(a);
|
||||
verifyRequiredAttributes(a);
|
||||
} catch (XmlPullParserException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
if (state.mDrawable != null && state.mDrawable.canApplyTheme()) {
|
||||
state.mDrawable.applyTheme(t);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canApplyTheme() {
|
||||
private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
|
||||
Theme theme) throws XmlPullParserException, IOException {
|
||||
Drawable dr = null;
|
||||
int type;
|
||||
final int outerDepth = parser.getDepth();
|
||||
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
|
||||
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
|
||||
if (type != XmlPullParser.START_TAG) {
|
||||
continue;
|
||||
}
|
||||
dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
|
||||
}
|
||||
|
||||
if (dr != null) {
|
||||
mState.mDrawable = dr;
|
||||
dr.setCallback(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException {
|
||||
// If we're not waiting on a theme, verify required attributes.
|
||||
if (mState.mDrawable == null && (mState.mThemeAttrs == null
|
||||
|| mState.mThemeAttrs[R.styleable.ScaleDrawable_drawable] == 0)) {
|
||||
throw new XmlPullParserException(a.getPositionDescription()
|
||||
+ ": <rotate> tag requires a 'drawable' attribute or "
|
||||
+ "child tag defining a drawable");
|
||||
}
|
||||
}
|
||||
|
||||
private void updateStateFromTypedArray(TypedArray a) {
|
||||
final RotateState state = mState;
|
||||
return state != null && state.mDrawable != null && state.mDrawable.canApplyTheme();
|
||||
|
||||
// Account for any configuration changes.
|
||||
state.mChangingConfigurations |= a.getChangingConfigurations();
|
||||
|
||||
// Extract the theme attributes, if any.
|
||||
state.mThemeAttrs = a.extractThemeAttrs();
|
||||
|
||||
if (a.hasValue(R.styleable.RotateDrawable_pivotX)) {
|
||||
final TypedValue tv = a.peekValue(R.styleable.RotateDrawable_pivotX);
|
||||
state.mPivotXRel = tv.type == TypedValue.TYPE_FRACTION;
|
||||
state.mPivotX = state.mPivotXRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
|
||||
}
|
||||
|
||||
if (a.hasValue(R.styleable.RotateDrawable_pivotY)) {
|
||||
final TypedValue tv = a.peekValue(R.styleable.RotateDrawable_pivotY);
|
||||
state.mPivotYRel = tv.type == TypedValue.TYPE_FRACTION;
|
||||
state.mPivotY = state.mPivotYRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
|
||||
}
|
||||
|
||||
state.mFromDegrees = a.getFloat(R.styleable.RotateDrawable_fromDegrees, state.mFromDegrees);
|
||||
state.mToDegrees = a.getFloat(R.styleable.RotateDrawable_toDegrees, state.mToDegrees);
|
||||
|
||||
final Drawable dr = a.getDrawable(R.styleable.RotateDrawable_drawable);
|
||||
if (dr != null) {
|
||||
state.mDrawable = dr;
|
||||
dr.setCallback(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -521,25 +526,28 @@ public class RotateDrawable extends Drawable implements Drawable.Callback {
|
||||
* rotations at the same time.
|
||||
*/
|
||||
final static class RotateState extends Drawable.ConstantState {
|
||||
Drawable mDrawable;
|
||||
|
||||
int[] mThemeAttrs;
|
||||
int mChangingConfigurations;
|
||||
|
||||
boolean mPivotXRel;
|
||||
float mPivotX;
|
||||
boolean mPivotYRel;
|
||||
float mPivotY;
|
||||
Drawable mDrawable;
|
||||
|
||||
float mFromDegrees;
|
||||
float mToDegrees;
|
||||
boolean mPivotXRel = true;
|
||||
float mPivotX = 0.5f;
|
||||
boolean mPivotYRel = true;
|
||||
float mPivotY = 0.5f;
|
||||
|
||||
float mCurrentDegrees;
|
||||
float mFromDegrees = 0.0f;
|
||||
float mToDegrees = 360.0f;
|
||||
|
||||
float mCurrentDegrees = 0.0f;
|
||||
|
||||
private boolean mCanConstantState;
|
||||
private boolean mCheckedConstantState;
|
||||
private boolean mCanConstantState;
|
||||
|
||||
public RotateState(RotateState orig, RotateDrawable owner, Resources res) {
|
||||
RotateState(RotateState orig, RotateDrawable owner, Resources res) {
|
||||
if (orig != null) {
|
||||
mThemeAttrs = orig.mThemeAttrs;
|
||||
mChangingConfigurations = orig.mChangingConfigurations;
|
||||
if (res != null) {
|
||||
mDrawable = orig.mDrawable.getConstantState().newDrawable(res);
|
||||
} else {
|
||||
@@ -553,12 +561,19 @@ public class RotateDrawable extends Drawable implements Drawable.Callback {
|
||||
mPivotX = orig.mPivotX;
|
||||
mPivotYRel = orig.mPivotYRel;
|
||||
mPivotY = orig.mPivotY;
|
||||
mFromDegrees = mCurrentDegrees = orig.mFromDegrees;
|
||||
mFromDegrees = orig.mFromDegrees;
|
||||
mToDegrees = orig.mToDegrees;
|
||||
mCanConstantState = mCheckedConstantState = true;
|
||||
mCurrentDegrees = orig.mCurrentDegrees;
|
||||
mCheckedConstantState = mCanConstantState = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canApplyTheme() {
|
||||
return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme())
|
||||
|| super.canApplyTheme();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable newDrawable() {
|
||||
return new RotateDrawable(this, null);
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package android.graphics.drawable;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
@@ -47,7 +49,7 @@ import java.io.IOException;
|
||||
* @attr ref android.R.styleable#ScaleDrawable_drawable
|
||||
*/
|
||||
public class ScaleDrawable extends Drawable implements Drawable.Callback {
|
||||
private ScaleState mScaleState;
|
||||
private ScaleState mState;
|
||||
private boolean mMutated;
|
||||
private final Rect mTmpRect = new Rect();
|
||||
|
||||
@@ -58,10 +60,10 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback {
|
||||
public ScaleDrawable(Drawable drawable, int gravity, float scaleWidth, float scaleHeight) {
|
||||
this(null, null);
|
||||
|
||||
mScaleState.mDrawable = drawable;
|
||||
mScaleState.mGravity = gravity;
|
||||
mScaleState.mScaleWidth = scaleWidth;
|
||||
mScaleState.mScaleHeight = scaleHeight;
|
||||
mState.mDrawable = drawable;
|
||||
mState.mGravity = gravity;
|
||||
mState.mScaleWidth = scaleWidth;
|
||||
mState.mScaleHeight = scaleHeight;
|
||||
|
||||
if (drawable != null) {
|
||||
drawable.setCallback(this);
|
||||
@@ -72,18 +74,18 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback {
|
||||
* Returns the drawable scaled by this ScaleDrawable.
|
||||
*/
|
||||
public Drawable getDrawable() {
|
||||
return mScaleState.mDrawable;
|
||||
return mState.mDrawable;
|
||||
}
|
||||
|
||||
private static float getPercent(TypedArray a, int name) {
|
||||
String s = a.getString(name);
|
||||
private static float getPercent(TypedArray a, int name, float defaultValue) {
|
||||
final String s = a.getString(name);
|
||||
if (s != null) {
|
||||
if (s.endsWith("%")) {
|
||||
String f = s.substring(0, s.length() - 1);
|
||||
return Float.parseFloat(f) / 100.0f;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -91,20 +93,48 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback {
|
||||
throws XmlPullParserException, IOException {
|
||||
super.inflate(r, parser, attrs, theme);
|
||||
|
||||
int type;
|
||||
final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.ScaleDrawable);
|
||||
|
||||
TypedArray a = obtainAttributes(
|
||||
r, theme, attrs, com.android.internal.R.styleable.ScaleDrawable);
|
||||
|
||||
float sw = getPercent(a, com.android.internal.R.styleable.ScaleDrawable_scaleWidth);
|
||||
float sh = getPercent(a, com.android.internal.R.styleable.ScaleDrawable_scaleHeight);
|
||||
int g = a.getInt(com.android.internal.R.styleable.ScaleDrawable_scaleGravity, Gravity.LEFT);
|
||||
boolean min = a.getBoolean(
|
||||
com.android.internal.R.styleable.ScaleDrawable_useIntrinsicSizeAsMinimum, false);
|
||||
Drawable dr = a.getDrawable(com.android.internal.R.styleable.ScaleDrawable_drawable);
|
||||
// Reset mDrawable to preserve old multiple-inflate behavior. This is
|
||||
// silly, but we have CTS tests that rely on it.
|
||||
mState.mDrawable = null;
|
||||
|
||||
updateStateFromTypedArray(a);
|
||||
inflateChildElements(r, parser, attrs, theme);
|
||||
verifyRequiredAttributes(a);
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyTheme(Theme t) {
|
||||
super.applyTheme(t);
|
||||
|
||||
final ScaleState state = mState;
|
||||
if (state == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (state.mThemeAttrs == null) {
|
||||
final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.ScaleDrawable);
|
||||
try {
|
||||
updateStateFromTypedArray(a);
|
||||
verifyRequiredAttributes(a);
|
||||
} catch (XmlPullParserException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
a.recycle();
|
||||
}
|
||||
}
|
||||
|
||||
if (state.mDrawable != null && state.mDrawable.canApplyTheme()) {
|
||||
state.mDrawable.applyTheme(t);
|
||||
}
|
||||
}
|
||||
|
||||
private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
|
||||
Theme theme) throws XmlPullParserException, IOException {
|
||||
Drawable dr = null;
|
||||
int type;
|
||||
final int outerDepth = parser.getDepth();
|
||||
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
|
||||
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
|
||||
@@ -114,38 +144,49 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback {
|
||||
dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
|
||||
}
|
||||
|
||||
if (dr == null) {
|
||||
throw new IllegalArgumentException("No drawable specified for <scale>");
|
||||
}
|
||||
|
||||
mScaleState.mDrawable = dr;
|
||||
mScaleState.mScaleWidth = sw;
|
||||
mScaleState.mScaleHeight = sh;
|
||||
mScaleState.mGravity = g;
|
||||
mScaleState.mUseIntrinsicSizeAsMin = min;
|
||||
if (dr != null) {
|
||||
mState.mDrawable = dr;
|
||||
dr.setCallback(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException {
|
||||
// If we're not waiting on a theme, verify required attributes.
|
||||
if (mState.mDrawable == null && (mState.mThemeAttrs == null
|
||||
|| mState.mThemeAttrs[R.styleable.ScaleDrawable_drawable] == 0)) {
|
||||
throw new XmlPullParserException(a.getPositionDescription()
|
||||
+ ": <scale> tag requires a 'drawable' attribute or "
|
||||
+ "child tag defining a drawable");
|
||||
}
|
||||
}
|
||||
|
||||
private void updateStateFromTypedArray(TypedArray a) {
|
||||
final ScaleState state = mState;
|
||||
|
||||
// Account for any configuration changes.
|
||||
state.mChangingConfigurations |= a.getChangingConfigurations();
|
||||
|
||||
// Extract the theme attributes, if any.
|
||||
state.mThemeAttrs = a.extractThemeAttrs();
|
||||
|
||||
state.mScaleWidth = getPercent(
|
||||
a, R.styleable.ScaleDrawable_scaleWidth, state.mScaleWidth);
|
||||
state.mScaleHeight = getPercent(
|
||||
a, R.styleable.ScaleDrawable_scaleHeight, state.mScaleHeight);
|
||||
state.mGravity = a.getInt(R.styleable.ScaleDrawable_scaleGravity, Gravity.LEFT);
|
||||
state.mUseIntrinsicSizeAsMin = a.getBoolean(
|
||||
R.styleable.ScaleDrawable_useIntrinsicSizeAsMinimum, false);
|
||||
|
||||
final Drawable dr = a.getDrawable(R.styleable.ScaleDrawable_drawable);
|
||||
if (dr != null) {
|
||||
state.mDrawable = dr;
|
||||
dr.setCallback(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyTheme(Theme t) {
|
||||
super.applyTheme(t);
|
||||
|
||||
final ScaleState state = mScaleState;
|
||||
if (state == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (state.mDrawable != null) {
|
||||
state.mDrawable.applyTheme(t);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canApplyTheme() {
|
||||
final ScaleState state = mScaleState;
|
||||
return state != null && state.mDrawable != null && state.mDrawable.canApplyTheme();
|
||||
return (mState != null && mState.canApplyTheme()) || super.canApplyTheme();
|
||||
}
|
||||
|
||||
// overrides from Drawable.Callback
|
||||
@@ -172,74 +213,74 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback {
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
if (mScaleState.mDrawable.getLevel() != 0)
|
||||
mScaleState.mDrawable.draw(canvas);
|
||||
if (mState.mDrawable.getLevel() != 0)
|
||||
mState.mDrawable.draw(canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChangingConfigurations() {
|
||||
return super.getChangingConfigurations()
|
||||
| mScaleState.mChangingConfigurations
|
||||
| mScaleState.mDrawable.getChangingConfigurations();
|
||||
| mState.mChangingConfigurations
|
||||
| mState.mDrawable.getChangingConfigurations();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getPadding(Rect padding) {
|
||||
// XXX need to adjust padding!
|
||||
return mScaleState.mDrawable.getPadding(padding);
|
||||
return mState.mDrawable.getPadding(padding);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setVisible(boolean visible, boolean restart) {
|
||||
mScaleState.mDrawable.setVisible(visible, restart);
|
||||
mState.mDrawable.setVisible(visible, restart);
|
||||
return super.setVisible(visible, restart);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
mScaleState.mDrawable.setAlpha(alpha);
|
||||
mState.mDrawable.setAlpha(alpha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAlpha() {
|
||||
return mScaleState.mDrawable.getAlpha();
|
||||
return mState.mDrawable.getAlpha();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(ColorFilter cf) {
|
||||
mScaleState.mDrawable.setColorFilter(cf);
|
||||
mState.mDrawable.setColorFilter(cf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTintList(ColorStateList tint) {
|
||||
mScaleState.mDrawable.setTintList(tint);
|
||||
mState.mDrawable.setTintList(tint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTintMode(Mode tintMode) {
|
||||
mScaleState.mDrawable.setTintMode(tintMode);
|
||||
mState.mDrawable.setTintMode(tintMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
return mScaleState.mDrawable.getOpacity();
|
||||
return mState.mDrawable.getOpacity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStateful() {
|
||||
return mScaleState.mDrawable.isStateful();
|
||||
return mState.mDrawable.isStateful();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onStateChange(int[] state) {
|
||||
boolean changed = mScaleState.mDrawable.setState(state);
|
||||
boolean changed = mState.mDrawable.setState(state);
|
||||
onBoundsChange(getBounds());
|
||||
return changed;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onLevelChange(int level) {
|
||||
mScaleState.mDrawable.setLevel(level);
|
||||
mState.mDrawable.setLevel(level);
|
||||
onBoundsChange(getBounds());
|
||||
invalidateSelf();
|
||||
return true;
|
||||
@@ -248,41 +289,41 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback {
|
||||
@Override
|
||||
protected void onBoundsChange(Rect bounds) {
|
||||
final Rect r = mTmpRect;
|
||||
final boolean min = mScaleState.mUseIntrinsicSizeAsMin;
|
||||
final boolean min = mState.mUseIntrinsicSizeAsMin;
|
||||
int level = getLevel();
|
||||
int w = bounds.width();
|
||||
if (mScaleState.mScaleWidth > 0) {
|
||||
final int iw = min ? mScaleState.mDrawable.getIntrinsicWidth() : 0;
|
||||
w -= (int) ((w - iw) * (10000 - level) * mScaleState.mScaleWidth / 10000);
|
||||
if (mState.mScaleWidth > 0) {
|
||||
final int iw = min ? mState.mDrawable.getIntrinsicWidth() : 0;
|
||||
w -= (int) ((w - iw) * (10000 - level) * mState.mScaleWidth / 10000);
|
||||
}
|
||||
int h = bounds.height();
|
||||
if (mScaleState.mScaleHeight > 0) {
|
||||
final int ih = min ? mScaleState.mDrawable.getIntrinsicHeight() : 0;
|
||||
h -= (int) ((h - ih) * (10000 - level) * mScaleState.mScaleHeight / 10000);
|
||||
if (mState.mScaleHeight > 0) {
|
||||
final int ih = min ? mState.mDrawable.getIntrinsicHeight() : 0;
|
||||
h -= (int) ((h - ih) * (10000 - level) * mState.mScaleHeight / 10000);
|
||||
}
|
||||
final int layoutDirection = getLayoutDirection();
|
||||
Gravity.apply(mScaleState.mGravity, w, h, bounds, r, layoutDirection);
|
||||
Gravity.apply(mState.mGravity, w, h, bounds, r, layoutDirection);
|
||||
|
||||
if (w > 0 && h > 0) {
|
||||
mScaleState.mDrawable.setBounds(r.left, r.top, r.right, r.bottom);
|
||||
mState.mDrawable.setBounds(r.left, r.top, r.right, r.bottom);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicWidth() {
|
||||
return mScaleState.mDrawable.getIntrinsicWidth();
|
||||
return mState.mDrawable.getIntrinsicWidth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicHeight() {
|
||||
return mScaleState.mDrawable.getIntrinsicHeight();
|
||||
return mState.mDrawable.getIntrinsicHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConstantState getConstantState() {
|
||||
if (mScaleState.canConstantState()) {
|
||||
mScaleState.mChangingConfigurations = getChangingConfigurations();
|
||||
return mScaleState;
|
||||
if (mState.canConstantState()) {
|
||||
mState.mChangingConfigurations = getChangingConfigurations();
|
||||
return mState;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -290,7 +331,7 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback {
|
||||
@Override
|
||||
public Drawable mutate() {
|
||||
if (!mMutated && super.mutate() == this) {
|
||||
mScaleState.mDrawable.mutate();
|
||||
mState.mDrawable.mutate();
|
||||
mMutated = true;
|
||||
}
|
||||
return this;
|
||||
@@ -301,23 +342,28 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback {
|
||||
*/
|
||||
public void clearMutated() {
|
||||
super.clearMutated();
|
||||
mScaleState.mDrawable.clearMutated();
|
||||
mState.mDrawable.clearMutated();
|
||||
mMutated = false;
|
||||
}
|
||||
|
||||
final static class ScaleState extends ConstantState {
|
||||
Drawable mDrawable;
|
||||
int[] mThemeAttrs;
|
||||
int mChangingConfigurations;
|
||||
float mScaleWidth;
|
||||
float mScaleHeight;
|
||||
int mGravity;
|
||||
boolean mUseIntrinsicSizeAsMin;
|
||||
|
||||
Drawable mDrawable;
|
||||
|
||||
float mScaleWidth = 1.0f;
|
||||
float mScaleHeight = 1.0f;
|
||||
int mGravity = Gravity.LEFT;
|
||||
boolean mUseIntrinsicSizeAsMin = false;
|
||||
|
||||
private boolean mCheckedConstantState;
|
||||
private boolean mCanConstantState;
|
||||
|
||||
ScaleState(ScaleState orig, ScaleDrawable owner, Resources res) {
|
||||
if (orig != null) {
|
||||
mThemeAttrs = orig.mThemeAttrs;
|
||||
mChangingConfigurations = orig.mChangingConfigurations;
|
||||
if (res != null) {
|
||||
mDrawable = orig.mDrawable.getConstantState().newDrawable(res);
|
||||
} else {
|
||||
@@ -335,6 +381,12 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canApplyTheme() {
|
||||
return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme())
|
||||
|| super.canApplyTheme();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable newDrawable() {
|
||||
return new ScaleDrawable(this, null);
|
||||
@@ -361,7 +413,7 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback {
|
||||
}
|
||||
|
||||
private ScaleDrawable(ScaleState state, Resources res) {
|
||||
mScaleState = new ScaleState(state, this, res);
|
||||
mState = new ScaleState(state, this, res);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -117,26 +117,48 @@ public class StateListDrawable extends DrawableContainer {
|
||||
@Override
|
||||
public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
|
||||
throws XmlPullParserException, IOException {
|
||||
|
||||
final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.StateListDrawable);
|
||||
|
||||
super.inflateWithAttributes(r, parser, a,
|
||||
R.styleable.StateListDrawable_visible);
|
||||
|
||||
mStateListState.setVariablePadding(a.getBoolean(
|
||||
R.styleable.StateListDrawable_variablePadding, false));
|
||||
mStateListState.setConstantSize(a.getBoolean(
|
||||
R.styleable.StateListDrawable_constantSize, false));
|
||||
mStateListState.setEnterFadeDuration(a.getInt(
|
||||
R.styleable.StateListDrawable_enterFadeDuration, 0));
|
||||
mStateListState.setExitFadeDuration(a.getInt(
|
||||
R.styleable.StateListDrawable_exitFadeDuration, 0));
|
||||
|
||||
setDither(a.getBoolean(R.styleable.StateListDrawable_dither, DEFAULT_DITHER));
|
||||
setAutoMirrored(a.getBoolean(R.styleable.StateListDrawable_autoMirrored, false));
|
||||
|
||||
super.inflateWithAttributes(r, parser, a, R.styleable.StateListDrawable_visible);
|
||||
updateStateFromTypedArray(a);
|
||||
a.recycle();
|
||||
|
||||
inflateChildElements(r, parser, attrs, theme);
|
||||
|
||||
onStateChange(getState());
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the constant state from the values in the typed array.
|
||||
*/
|
||||
private void updateStateFromTypedArray(TypedArray a) {
|
||||
final StateListState state = mStateListState;
|
||||
|
||||
// Account for any configuration changes.
|
||||
state.mChangingConfigurations |= a.getChangingConfigurations();
|
||||
|
||||
// Extract the theme attributes, if any.
|
||||
state.mThemeAttrs = a.extractThemeAttrs();
|
||||
|
||||
state.mVariablePadding = a.getBoolean(
|
||||
R.styleable.StateListDrawable_variablePadding, state.mVariablePadding);
|
||||
state.mConstantSize = a.getBoolean(
|
||||
R.styleable.StateListDrawable_constantSize, state.mConstantSize);
|
||||
state.mEnterFadeDuration = a.getInt(
|
||||
R.styleable.StateListDrawable_enterFadeDuration, state.mEnterFadeDuration);
|
||||
state.mExitFadeDuration = a.getInt(
|
||||
R.styleable.StateListDrawable_exitFadeDuration, state.mExitFadeDuration);
|
||||
state.mDither = a.getBoolean(
|
||||
R.styleable.StateListDrawable_dither, state.mDither);
|
||||
state.mAutoMirrored = a.getBoolean(
|
||||
R.styleable.StateListDrawable_autoMirrored, state.mAutoMirrored);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inflates child elements from XML.
|
||||
*/
|
||||
private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
|
||||
Theme theme) throws XmlPullParserException, IOException {
|
||||
final StateListState state = mStateListState;
|
||||
final int innerDepth = parser.getDepth() + 1;
|
||||
int type;
|
||||
int depth;
|
||||
@@ -185,10 +207,8 @@ public class StateListDrawable extends DrawableContainer {
|
||||
dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
|
||||
}
|
||||
|
||||
mStateListState.addStateSet(states, dr);
|
||||
state.addStateSet(states, dr);
|
||||
}
|
||||
|
||||
onStateChange(getState());
|
||||
}
|
||||
|
||||
StateListState getStateListState() {
|
||||
@@ -282,6 +302,7 @@ public class StateListDrawable extends DrawableContainer {
|
||||
}
|
||||
|
||||
static class StateListState extends DrawableContainerState {
|
||||
int[] mThemeAttrs;
|
||||
int[][] mStateSets;
|
||||
|
||||
StateListState(StateListState orig, StateListDrawable owner, Resources res) {
|
||||
@@ -298,7 +319,11 @@ public class StateListDrawable extends DrawableContainer {
|
||||
mStateSets[i] = set.clone();
|
||||
}
|
||||
}
|
||||
|
||||
mThemeAttrs = orig.mThemeAttrs;
|
||||
mStateSets = Arrays.copyOf(orig.mStateSets, orig.mStateSets.length);
|
||||
} else {
|
||||
mThemeAttrs = null;
|
||||
mStateSets = new int[getCapacity()][];
|
||||
}
|
||||
}
|
||||
@@ -330,6 +355,11 @@ public class StateListDrawable extends DrawableContainer {
|
||||
return new StateListDrawable(this, res);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canApplyTheme() {
|
||||
return mThemeAttrs != null || super.canApplyTheme();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void growArray(int oldSize, int newSize) {
|
||||
super.growArray(oldSize, newSize);
|
||||
|
||||
@@ -361,7 +361,7 @@ public class VectorDrawable extends Drawable {
|
||||
|
||||
@Override
|
||||
public boolean canApplyTheme() {
|
||||
return super.canApplyTheme() || mVectorState != null && mVectorState.canApplyTheme();
|
||||
return (mVectorState != null && mVectorState.canApplyTheme()) || super.canApplyTheme();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -750,8 +750,8 @@ public class VectorDrawable extends Drawable {
|
||||
|
||||
@Override
|
||||
public boolean canApplyTheme() {
|
||||
return super.canApplyTheme() || mThemeAttrs != null
|
||||
|| (mVPathRenderer != null && mVPathRenderer.canApplyTheme());
|
||||
return mThemeAttrs != null || (mVPathRenderer != null && mVPathRenderer.canApplyTheme())
|
||||
|| super.canApplyTheme();
|
||||
}
|
||||
|
||||
public VectorDrawableState() {
|
||||
|
||||
Reference in New Issue
Block a user