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