1f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy/* 2f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy * Copyright (C) 2009 The Android Open Source Project 3f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy * 4f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy * Licensed under the Apache License, Version 2.0 (the "License"); 5f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy * you may not use this file except in compliance with the License. 6f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy * You may obtain a copy of the License at 7f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy * 8f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy * http://www.apache.org/licenses/LICENSE-2.0 9f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy * 10f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy * Unless required by applicable law or agreed to in writing, software 11f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy * distributed under the License is distributed on an "AS IS" BASIS, 12f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy * See the License for the specific language governing permissions and 14f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy * limitations under the License. 15f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy */ 16f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 17f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guypackage android.graphics.drawable; 18f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 19f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guyimport android.graphics.Canvas; 20f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guyimport android.graphics.Rect; 21f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guyimport android.graphics.ColorFilter; 22f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guyimport android.content.res.Resources; 23f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guyimport android.content.res.TypedArray; 24f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guyimport android.util.AttributeSet; 25f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guyimport android.util.TypedValue; 26f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guyimport android.util.Log; 27f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guyimport android.os.SystemClock; 28f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guyimport org.xmlpull.v1.XmlPullParser; 29f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guyimport org.xmlpull.v1.XmlPullParserException; 30f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 31f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guyimport java.io.IOException; 32f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 33f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guyimport com.android.internal.R; 34f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 35f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy/** 36f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy * @hide 37f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy */ 38b5537c452271634b6ff3981b0624fa65384abd5bRomain Guypublic class AnimatedRotateDrawable extends Drawable implements Drawable.Callback, Runnable, 39b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy Animatable { 40b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy 41f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy private AnimatedRotateState mState; 42f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy private boolean mMutated; 43f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy private float mCurrentDegrees; 44f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy private float mIncrement; 45b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy private boolean mRunning; 46f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 47f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy public AnimatedRotateDrawable() { 48c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn this(null, null); 49f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 50f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 51c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn private AnimatedRotateDrawable(AnimatedRotateState rotateState, Resources res) { 52c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn mState = new AnimatedRotateState(rotateState, this, res); 53f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy init(); 54f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 55f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 56f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy private void init() { 57f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy final AnimatedRotateState state = mState; 580d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey mIncrement = 360.0f / state.mFramesCount; 59f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy final Drawable drawable = state.mDrawable; 60f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy if (drawable != null) { 61f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy drawable.setFilterBitmap(true); 62f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy if (drawable instanceof BitmapDrawable) { 63f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy ((BitmapDrawable) drawable).setAntiAlias(true); 64f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 65f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 66f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 67f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 680d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey @Override 69f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy public void draw(Canvas canvas) { 70f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy int saveCount = canvas.save(); 71f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 72f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy final AnimatedRotateState st = mState; 73f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy final Drawable drawable = st.mDrawable; 74f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy final Rect bounds = drawable.getBounds(); 75f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 76f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy int w = bounds.right - bounds.left; 77f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy int h = bounds.bottom - bounds.top; 78f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 79f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy float px = st.mPivotXRel ? (w * st.mPivotX) : st.mPivotX; 80f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy float py = st.mPivotYRel ? (h * st.mPivotY) : st.mPivotY; 81f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 82e5cdb6c8394e321266fb8940fdd0c97b2f87b2f3Chet Haase canvas.rotate(mCurrentDegrees, px + bounds.left, py + bounds.top); 83f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 84f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy drawable.draw(canvas); 85f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 86f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy canvas.restoreToCount(saveCount); 87f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 88b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy 89b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy public void start() { 90b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy if (!mRunning) { 91b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy mRunning = true; 92b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy nextFrame(); 93b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy } 94b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy } 95b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy 96b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy public void stop() { 97b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy mRunning = false; 98b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy unscheduleSelf(this); 99b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy } 100b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy 101b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy public boolean isRunning() { 102b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy return mRunning; 103b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy } 104b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy 105f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy private void nextFrame() { 106f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy unscheduleSelf(this); 107f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy scheduleSelf(this, SystemClock.uptimeMillis() + mState.mFrameDuration); 108f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 109f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 110f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy public void run() { 111f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy // TODO: This should be computed in draw(Canvas), based on the amount 112f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy // of time since the last frame drawn 113f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy mCurrentDegrees += mIncrement; 114f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy if (mCurrentDegrees > (360.0f - mIncrement)) { 115f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy mCurrentDegrees = 0.0f; 116f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 117f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy invalidateSelf(); 118b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy nextFrame(); 119f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 120f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 121f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy @Override 122f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy public boolean setVisible(boolean visible, boolean restart) { 123f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy mState.mDrawable.setVisible(visible, restart); 124f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy boolean changed = super.setVisible(visible, restart); 125f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy if (visible) { 126f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy if (changed || restart) { 127f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy mCurrentDegrees = 0.0f; 128f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy nextFrame(); 129f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 130f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } else { 131f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy unscheduleSelf(this); 132f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 133f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy return changed; 134f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 135f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 136f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy /** 137f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy * Returns the drawable rotated by this RotateDrawable. 138f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy */ 139f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy public Drawable getDrawable() { 140f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy return mState.mDrawable; 141f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 142f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 143f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy @Override 144f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy public int getChangingConfigurations() { 145f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy return super.getChangingConfigurations() 146f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy | mState.mChangingConfigurations 147f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy | mState.mDrawable.getChangingConfigurations(); 148f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 149f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 1500d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey @Override 151f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy public void setAlpha(int alpha) { 152f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy mState.mDrawable.setAlpha(alpha); 153f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 154f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 1550d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey @Override 156f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy public void setColorFilter(ColorFilter cf) { 157f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy mState.mDrawable.setColorFilter(cf); 158f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 159f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 1600d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey @Override 161f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy public int getOpacity() { 162f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy return mState.mDrawable.getOpacity(); 163f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 164f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 165f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy public void invalidateDrawable(Drawable who) { 166f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy final Callback callback = getCallback(); 167f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy if (callback != null) { 168f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy callback.invalidateDrawable(this); 169f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 170f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 171f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 172f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy public void scheduleDrawable(Drawable who, Runnable what, long when) { 173f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy final Callback callback = getCallback(); 174f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy if (callback != null) { 175f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy callback.scheduleDrawable(this, what, when); 176f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 177f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 178f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 179f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy public void unscheduleDrawable(Drawable who, Runnable what) { 180f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy final Callback callback = getCallback(); 181f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy if (callback != null) { 182f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy callback.unscheduleDrawable(this, what); 183f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 184f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 185f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 186f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy @Override 187f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy public boolean getPadding(Rect padding) { 188f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy return mState.mDrawable.getPadding(padding); 189f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 190f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 191f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy @Override 192f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy public boolean isStateful() { 193f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy return mState.mDrawable.isStateful(); 194f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 195f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 196f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy @Override 197f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy protected void onBoundsChange(Rect bounds) { 198f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy mState.mDrawable.setBounds(bounds.left, bounds.top, bounds.right, bounds.bottom); 199f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 200f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 201f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy @Override 202f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy public int getIntrinsicWidth() { 203f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy return mState.mDrawable.getIntrinsicWidth(); 204f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 205f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 206f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy @Override 207f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy public int getIntrinsicHeight() { 208f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy return mState.mDrawable.getIntrinsicHeight(); 209f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 210f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 211f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy @Override 212f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy public ConstantState getConstantState() { 213f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy if (mState.canConstantState()) { 2146efd2bad954e0e5bd74916a32f036a0f149dcd4dChristopher Lais mState.mChangingConfigurations = getChangingConfigurations(); 215f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy return mState; 216f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 217f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy return null; 218f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 219f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 220f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy @Override 221f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs) 222f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy throws XmlPullParserException, IOException { 223f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 224f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy final TypedArray a = r.obtainAttributes(attrs, R.styleable.AnimatedRotateDrawable); 225f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 226f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy super.inflateWithAttributes(r, parser, a, R.styleable.AnimatedRotateDrawable_visible); 227f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 228f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy TypedValue tv = a.peekValue(R.styleable.AnimatedRotateDrawable_pivotX); 229f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy final boolean pivotXRel = tv.type == TypedValue.TYPE_FRACTION; 230f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy final float pivotX = pivotXRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat(); 231f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 232f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy tv = a.peekValue(R.styleable.AnimatedRotateDrawable_pivotY); 233f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy final boolean pivotYRel = tv.type == TypedValue.TYPE_FRACTION; 234f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy final float pivotY = pivotYRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat(); 2350d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey 2360d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey setFramesCount(a.getInt(R.styleable.AnimatedRotateDrawable_framesCount, 12)); 2370d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey setFramesDuration(a.getInt(R.styleable.AnimatedRotateDrawable_frameDuration, 150)); 2380d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey 239f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy final int res = a.getResourceId(R.styleable.AnimatedRotateDrawable_drawable, 0); 240f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy Drawable drawable = null; 241f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy if (res > 0) { 242f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy drawable = r.getDrawable(res); 243f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 244f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 245f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy a.recycle(); 246f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 247f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy int outerDepth = parser.getDepth(); 248f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy int type; 249f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && 250f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 251f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 252f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy if (type != XmlPullParser.START_TAG) { 253f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy continue; 254f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 255f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 256f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy if ((drawable = Drawable.createFromXmlInner(r, parser, attrs)) == null) { 257f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy Log.w("drawable", "Bad element under <animated-rotate>: " 258f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy + parser .getName()); 259f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 260f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 261f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 262f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy if (drawable == null) { 263f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy Log.w("drawable", "No drawable specified for <animated-rotate>"); 264f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 265f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 266f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy final AnimatedRotateState rotateState = mState; 267f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy rotateState.mDrawable = drawable; 268f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy rotateState.mPivotXRel = pivotXRel; 269f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy rotateState.mPivotX = pivotX; 270f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy rotateState.mPivotYRel = pivotYRel; 271f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy rotateState.mPivotY = pivotY; 272f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 273f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy init(); 274f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 275f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy if (drawable != null) { 276f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy drawable.setCallback(this); 277f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 278f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 279f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 2800d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey public void setFramesCount(int framesCount) { 2810d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey mState.mFramesCount = framesCount; 2820d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey mIncrement = 360.0f / mState.mFramesCount; 2830d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey } 2840d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey 2850d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey public void setFramesDuration(int framesDuration) { 2860d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey mState.mFrameDuration = framesDuration; 2870d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey } 2880d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey 289f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy @Override 290f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy public Drawable mutate() { 291f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy if (!mMutated && super.mutate() == this) { 292f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy mState.mDrawable.mutate(); 293f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy mMutated = true; 294f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 295f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy return this; 296f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 297f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 298f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy final static class AnimatedRotateState extends Drawable.ConstantState { 299f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy Drawable mDrawable; 300f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 301f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy int mChangingConfigurations; 302f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 303f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy boolean mPivotXRel; 304f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy float mPivotX; 305f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy boolean mPivotYRel; 306f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy float mPivotY; 307f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy int mFrameDuration; 308f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy int mFramesCount; 309f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 310f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy private boolean mCanConstantState; 311f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy private boolean mCheckedConstantState; 312f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 313c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn public AnimatedRotateState(AnimatedRotateState source, AnimatedRotateDrawable owner, 314c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn Resources res) { 315f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy if (source != null) { 316c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn if (res != null) { 317c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn mDrawable = source.mDrawable.getConstantState().newDrawable(res); 318c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn } else { 319c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn mDrawable = source.mDrawable.getConstantState().newDrawable(); 320c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn } 321f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy mDrawable.setCallback(owner); 322f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy mPivotXRel = source.mPivotXRel; 323f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy mPivotX = source.mPivotX; 324f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy mPivotYRel = source.mPivotYRel; 325f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy mPivotY = source.mPivotY; 326f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy mFramesCount = source.mFramesCount; 327f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy mFrameDuration = source.mFrameDuration; 328f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy mCanConstantState = mCheckedConstantState = true; 329f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 330f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 331f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 332f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy @Override 333f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy public Drawable newDrawable() { 334c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn return new AnimatedRotateDrawable(this, null); 335c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn } 336c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn 337c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn @Override 338c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn public Drawable newDrawable(Resources res) { 339c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn return new AnimatedRotateDrawable(this, res); 340f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 341f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 342f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy @Override 343f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy public int getChangingConfigurations() { 344f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy return mChangingConfigurations; 345f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 346f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 347f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy public boolean canConstantState() { 348f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy if (!mCheckedConstantState) { 349f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy mCanConstantState = mDrawable.getConstantState() != null; 350f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy mCheckedConstantState = true; 351f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 352f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy 353f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy return mCanConstantState; 354f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 355f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy } 356f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy} 357