Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 425b1dc8 authored by Alan Viverette's avatar Alan Viverette Committed by Android (Google) Code Review
Browse files

Merge "Add theme and config change support to more Drawable types" into lmp-mr1-dev

parents 10450405 d21fd9d1
Loading
Loading
Loading
Loading
+103 −57
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package android.graphics.drawable;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.ColorFilter;
@@ -41,6 +43,7 @@ import com.android.internal.R;
 */
public class AnimatedRotateDrawable extends Drawable implements Drawable.Callback, Runnable,
        Animatable {
    private static final String TAG = "AnimatedRotateDrawable";

    private AnimatedRotateState mState;
    private boolean mMutated;
@@ -185,6 +188,11 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac
        return mState.mDrawable.getOpacity();
    }

    @Override
    public boolean canApplyTheme() {
        return (mState != null && mState.canApplyTheme()) || super.canApplyTheme();
    }

    @Override
    public void invalidateDrawable(Drawable who) {
        final Callback callback = getCallback();
@@ -254,83 +262,113 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac
    }

    @Override
    public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
    public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser,
            @NonNull AttributeSet attrs, @Nullable Theme theme)
            throws XmlPullParserException, IOException {

        final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.AnimatedRotateDrawable);

        super.inflateWithAttributes(r, parser, a, R.styleable.AnimatedRotateDrawable_visible);
        updateStateFromTypedArray(a);
        a.recycle();

        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();
        inflateChildElements(r, parser, attrs, theme);

        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();
        init();
    }

        setFramesCount(a.getInt(R.styleable.AnimatedRotateDrawable_framesCount, 12));
        setFramesDuration(a.getInt(R.styleable.AnimatedRotateDrawable_frameDuration, 150));
    @Override
    public void applyTheme(@Nullable Theme t) {
        super.applyTheme(t);

        final int res = a.getResourceId(R.styleable.AnimatedRotateDrawable_drawable, 0);
        Drawable drawable = null;
        if (res > 0) {
            drawable = r.getDrawable(res, theme);
        final AnimatedRotateState state = mState;
        if (state == null) {
            return;
        }

        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();

        int outerDepth = parser.getDepth();
        int type;
        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT &&
               (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {

            if (type != XmlPullParser.START_TAG) {
                continue;
            }

            if ((drawable = Drawable.createFromXmlInner(r, parser, attrs, theme)) == null) {
                Log.w("drawable", "Bad element under <animated-rotate>: "
                        + parser .getName());
        }

        if (state.mDrawable != null && state.mDrawable.canApplyTheme()) {
            state.mDrawable.applyTheme(t);
        }

        if (drawable == null) {
            Log.w("drawable", "No drawable specified for <animated-rotate>");
        init();
    }

        final AnimatedRotateState rotateState = mState;
        rotateState.mDrawable = drawable;
        rotateState.mPivotXRel = pivotXRel;
        rotateState.mPivotX = pivotX;
        rotateState.mPivotYRel = pivotYRel;
        rotateState.mPivotY = pivotY;
    private void updateStateFromTypedArray(TypedArray a) {
        final AnimatedRotateState state = mState;

        init();
        // Account for any configuration changes.
        state.mChangingConfigurations |= a.getChangingConfigurations();

        if (drawable != null) {
            drawable.setCallback(this);
        // 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();
        }

    @Override
    public void applyTheme(Theme t) {
        super.applyTheme(t);
        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);
        }
    }

    private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
            Theme theme) throws XmlPullParserException, IOException {
        final AnimatedRotateState state = mState;
        if (state == null) {
            return;

        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 (state.mDrawable != null) {
            state.mDrawable.applyTheme(t);
            if ((dr = Drawable.createFromXmlInner(r, parser, attrs, theme)) == null) {
                Log.w(TAG, "Bad element under <animated-rotate>: " + parser.getName());
            }
        }

    @Override
    public boolean canApplyTheme() {
        final AnimatedRotateState state = mState;
        return state != null && state.mDrawable != null && state.mDrawable.canApplyTheme();
        if (dr != null) {
            state.mDrawable = dr;
            dr.setCallback(this);
        }
    }

    private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException {
        // If we're not waiting on a theme, verify required attributes.
        if (mState.mDrawable == null && (mState.mThemeAttrs == null
                || mState.mThemeAttrs[R.styleable.AnimatedRotateDrawable_drawable] == 0)) {
            throw new XmlPullParserException(a.getPositionDescription()
                    + ": <animated-rotate> tag requires a 'drawable' attribute or "
                    + "child tag defining a drawable");
        }
    }

    public void setFramesCount(int framesCount) {
@@ -362,15 +400,16 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac

    final static class AnimatedRotateState extends Drawable.ConstantState {
        Drawable mDrawable;
        int[] mThemeAttrs;

        int mChangingConfigurations;

        boolean mPivotXRel;
        float mPivotX;
        boolean mPivotYRel;
        float mPivotY;
        int mFrameDuration;
        int mFramesCount;
        boolean mPivotXRel = false;
        float mPivotX = 0;
        boolean mPivotYRel = false;
        float mPivotY = 0;
        int mFrameDuration = 150;
        int mFramesCount = 12;

        private boolean mCanConstantState;
        private boolean mCheckedConstantState;
@@ -387,6 +426,7 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac
                mDrawable.setLayoutDirection(orig.mDrawable.getLayoutDirection());
                mDrawable.setBounds(orig.mDrawable.getBounds());
                mDrawable.setLevel(orig.mDrawable.getLevel());
                mThemeAttrs = orig.mThemeAttrs;
                mPivotXRel = orig.mPivotXRel;
                mPivotX = orig.mPivotX;
                mPivotYRel = orig.mPivotYRel;
@@ -407,6 +447,12 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac
            return new AnimatedRotateDrawable(this, res);
        }

        @Override
        public boolean canApplyTheme() {
            return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme())
                    || super.canApplyTheme();
        }

        @Override
        public int getChangingConfigurations() {
            return mChangingConfigurations;
+58 −14
Original line number Diff line number Diff line
@@ -347,24 +347,62 @@ public class AnimatedStateListDrawable extends StateListDrawable {
            throws XmlPullParserException, IOException {
        final TypedArray a = obtainAttributes(
                r, theme, attrs, R.styleable.AnimatedStateListDrawable);

        super.inflateWithAttributes(r, parser, a, R.styleable.AnimatedStateListDrawable_visible);
        updateStateFromTypedArray(a);
        a.recycle();

        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));
        inflateChildElements(r, parser, attrs, theme);

        setDither(a.getBoolean(R.styleable.AnimatedStateListDrawable_dither, true));
        setAutoMirrored(a.getBoolean(R.styleable.AnimatedStateListDrawable_autoMirrored, false));
        init();
    }

    @Override
    public void applyTheme(@Nullable Theme theme) {
        super.applyTheme(theme);

        final AnimatedStateListState state = mState;
        if (state == null || !state.canApplyTheme()) {
            return;
        }

        final TypedArray a = theme.resolveAttributes(
                state.mAnimThemeAttrs, R.styleable.AnimatedRotateDrawable);
        updateStateFromTypedArray(a);
        a.recycle();

        init();
    }

    private void updateStateFromTypedArray(TypedArray a) {
        final AnimatedStateListState state = mState;

        // Account for any configuration changes.
        state.mChangingConfigurations |= a.getChangingConfigurations();

        // Extract the theme attributes, if any.
        state.mAnimThemeAttrs = a.extractThemeAttrs();

        state.setVariablePadding(a.getBoolean(
                R.styleable.AnimatedStateListDrawable_variablePadding, state.mVariablePadding));
        state.setConstantSize(a.getBoolean(
                R.styleable.AnimatedStateListDrawable_constantSize, state.mConstantSize));
        state.setEnterFadeDuration(a.getInt(
                R.styleable.AnimatedStateListDrawable_enterFadeDuration, state.mEnterFadeDuration));
        state.setExitFadeDuration(a.getInt(
                R.styleable.AnimatedStateListDrawable_exitFadeDuration, state.mExitFadeDuration));

        setDither(a.getBoolean(
                R.styleable.AnimatedStateListDrawable_dither, state.mDither));
        setAutoMirrored(a.getBoolean(
                R.styleable.AnimatedStateListDrawable_autoMirrored, state.mAutoMirrored));
    }

    private void init() {
        onStateChange(getState());
    }

    private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
            Theme theme) throws XmlPullParserException, IOException {
        int type;

        final int innerDepth = parser.getDepth() + 1;
@@ -386,8 +424,6 @@ public class AnimatedStateListDrawable extends StateListDrawable {
                parseTransition(r, parser, attrs, theme);
            }
        }

        onStateChange(getState());
    }

    private int parseTransition(@NonNull Resources r, @NonNull XmlPullParser parser,
@@ -507,6 +543,8 @@ public class AnimatedStateListDrawable extends StateListDrawable {
        private static final int REVERSE_SHIFT = 32;
        private static final int REVERSE_MASK = 0x1;

        int[] mAnimThemeAttrs;

        final LongSparseLongArray mTransitions;
        final SparseIntArray mStateIds;

@@ -515,6 +553,7 @@ public class AnimatedStateListDrawable extends StateListDrawable {
            super(orig, owner, res);

            if (orig != null) {
                mAnimThemeAttrs = orig.mAnimThemeAttrs;
                mTransitions = orig.mTransitions.clone();
                mStateIds = orig.mStateIds.clone();
            } else {
@@ -565,6 +604,11 @@ public class AnimatedStateListDrawable extends StateListDrawable {
            return (mTransitions.get(keyFromTo, -1) >> REVERSE_SHIFT & REVERSE_MASK) == 1;
        }

        @Override
        public boolean canApplyTheme() {
            return mAnimThemeAttrs != null || super.canApplyTheme();
        }

        @Override
        public Drawable newDrawable() {
            return new AnimatedStateListDrawable(this, null);
+8 −3
Original line number Diff line number Diff line
@@ -316,9 +316,8 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable {

    @Override
    public boolean canApplyTheme() {
        return super.canApplyTheme() || mAnimatedVectorState != null
                && mAnimatedVectorState.mVectorDrawable != null
                && mAnimatedVectorState.mVectorDrawable.canApplyTheme();
        return (mAnimatedVectorState != null && mAnimatedVectorState.canApplyTheme())
                || super.canApplyTheme();
    }

    @Override
@@ -373,6 +372,12 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable {
            }
        }

        @Override
        public boolean canApplyTheme() {
            return (mVectorDrawable != null && mVectorDrawable.canApplyTheme())
                    || super.canApplyTheme();
        }

        @Override
        public Drawable newDrawable() {
            return new AnimatedVectorDrawable(this, null);
+31 −27
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package android.graphics.drawable;

import com.android.internal.R;

import java.io.IOException;

import org.xmlpull.v1.XmlPullParser;
@@ -271,27 +273,25 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An
    @Override
    public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
            throws XmlPullParserException, IOException {
        final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.AnimationDrawable);
        super.inflateWithAttributes(r, parser, a, R.styleable.AnimationDrawable_visible);
        updateStateFromTypedArray(a);
        a.recycle();

        TypedArray a = obtainAttributes(r, theme, attrs,
                com.android.internal.R.styleable.AnimationDrawable);

        super.inflateWithAttributes(r, parser, a,
                com.android.internal.R.styleable.AnimationDrawable_visible);

        mAnimationState.setVariablePadding(a.getBoolean(
                com.android.internal.R.styleable.AnimationDrawable_variablePadding, false));

        mAnimationState.mOneShot = a.getBoolean(
                com.android.internal.R.styleable.AnimationDrawable_oneshot, false);
        inflateChildElements(r, parser, attrs, theme);

        a.recycle();
        setFrame(0, true, false);
    }

    private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
            Theme theme) throws XmlPullParserException, IOException {
        TypedArray a;
        int type;

        final int innerDepth = parser.getDepth()+1;
        int depth;
        while ((type=parser.next()) != XmlPullParser.END_DOCUMENT &&
                ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
        while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
                && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
            if (type != XmlPullParser.START_TAG) {
                continue;
            }
@@ -300,17 +300,15 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An
                continue;
            }

            a = obtainAttributes(
                    r, theme, attrs, com.android.internal.R.styleable.AnimationDrawableItem);
            int duration = a.getInt(
                    com.android.internal.R.styleable.AnimationDrawableItem_duration, -1);
            a = obtainAttributes(r, theme, attrs, R.styleable.AnimationDrawableItem);

            final int duration = a.getInt(R.styleable.AnimationDrawableItem_duration, -1);
            if (duration < 0) {
                throw new XmlPullParserException(
                        parser.getPositionDescription()
                throw new XmlPullParserException(parser.getPositionDescription()
                        + ": <item> tag requires a 'duration' attribute");
            }
            int drawableRes = a.getResourceId(
                    com.android.internal.R.styleable.AnimationDrawableItem_drawable, 0);

            final int drawableRes = a.getResourceId(R.styleable.AnimationDrawableItem_drawable, 0);

            a.recycle();

@@ -322,9 +320,9 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An
                    // Empty
                }
                if (type != XmlPullParser.START_TAG) {
                    throw new XmlPullParserException(parser.getPositionDescription() +
                            ": <item> tag requires a 'drawable' attribute or child tag" +
                            " defining a drawable");
                    throw new XmlPullParserException(parser.getPositionDescription()
                            + ": <item> tag requires a 'drawable' attribute or child tag"
                            + " defining a drawable");
                }
                dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
            }
@@ -334,8 +332,14 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An
                dr.setCallback(this);
            }
        }
    }

        setFrame(0, true, false);
    private void updateStateFromTypedArray(TypedArray a) {
        mAnimationState.mVariablePadding = a.getBoolean(
                R.styleable.AnimationDrawable_variablePadding, mAnimationState.mVariablePadding);

        mAnimationState.mOneShot = a.getBoolean(
                R.styleable.AnimationDrawable_oneshot, mAnimationState.mOneShot);
    }

    @Override
@@ -357,7 +361,7 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An

    private final static class AnimationState extends DrawableContainerState {
        private int[] mDurations;
        private boolean mOneShot;
        private boolean mOneShot = false;

        AnimationState(AnimationState orig, AnimationDrawable owner,
                Resources res) {
+105 −56

File changed.

Preview size limit exceeded, changes collapsed.

Loading