13060421045d4d9e411797f91bb509824b03e33fbJim Miller/*
23060421045d4d9e411797f91bb509824b03e33fbJim Miller * Copyright (C) 2010 The Android Open Source Project
33060421045d4d9e411797f91bb509824b03e33fbJim Miller *
43060421045d4d9e411797f91bb509824b03e33fbJim Miller * Licensed under the Apache License, Version 2.0 (the "License");
53060421045d4d9e411797f91bb509824b03e33fbJim Miller * you may not use this file except in compliance with the License.
63060421045d4d9e411797f91bb509824b03e33fbJim Miller * You may obtain a copy of the License at
73060421045d4d9e411797f91bb509824b03e33fbJim Miller *
83060421045d4d9e411797f91bb509824b03e33fbJim Miller *      http://www.apache.org/licenses/LICENSE-2.0
93060421045d4d9e411797f91bb509824b03e33fbJim Miller *
103060421045d4d9e411797f91bb509824b03e33fbJim Miller * Unless required by applicable law or agreed to in writing, software
113060421045d4d9e411797f91bb509824b03e33fbJim Miller * distributed under the License is distributed on an "AS IS" BASIS,
123060421045d4d9e411797f91bb509824b03e33fbJim Miller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133060421045d4d9e411797f91bb509824b03e33fbJim Miller * See the License for the specific language governing permissions and
143060421045d4d9e411797f91bb509824b03e33fbJim Miller * limitations under the License.
153060421045d4d9e411797f91bb509824b03e33fbJim Miller */
163060421045d4d9e411797f91bb509824b03e33fbJim Miller
173060421045d4d9e411797f91bb509824b03e33fbJim Millerpackage com.android.internal.widget;
183060421045d4d9e411797f91bb509824b03e33fbJim Miller
193060421045d4d9e411797f91bb509824b03e33fbJim Millerimport java.util.ArrayList;
203060421045d4d9e411797f91bb509824b03e33fbJim Miller
213060421045d4d9e411797f91bb509824b03e33fbJim Millerimport android.animation.Animator;
223060421045d4d9e411797f91bb509824b03e33fbJim Millerimport android.animation.ObjectAnimator;
233060421045d4d9e411797f91bb509824b03e33fbJim Millerimport android.animation.ValueAnimator;
243060421045d4d9e411797f91bb509824b03e33fbJim Millerimport android.animation.Animator.AnimatorListener;
253060421045d4d9e411797f91bb509824b03e33fbJim Millerimport android.graphics.Canvas;
263060421045d4d9e411797f91bb509824b03e33fbJim Millerimport android.graphics.drawable.BitmapDrawable;
273060421045d4d9e411797f91bb509824b03e33fbJim Millerimport android.util.Log;
283060421045d4d9e411797f91bb509824b03e33fbJim Millerimport android.view.animation.DecelerateInterpolator;
293060421045d4d9e411797f91bb509824b03e33fbJim Miller
303060421045d4d9e411797f91bb509824b03e33fbJim Miller/**
313060421045d4d9e411797f91bb509824b03e33fbJim Miller * This class is a container for a Drawable with multiple animated properties.
323060421045d4d9e411797f91bb509824b03e33fbJim Miller *
333060421045d4d9e411797f91bb509824b03e33fbJim Miller */
343060421045d4d9e411797f91bb509824b03e33fbJim Millerpublic class DrawableHolder implements AnimatorListener {
353060421045d4d9e411797f91bb509824b03e33fbJim Miller    public static final DecelerateInterpolator EASE_OUT_INTERPOLATOR = new DecelerateInterpolator();
363060421045d4d9e411797f91bb509824b03e33fbJim Miller    private static final String TAG = "DrawableHolder";
373060421045d4d9e411797f91bb509824b03e33fbJim Miller    private static final boolean DBG = false;
383060421045d4d9e411797f91bb509824b03e33fbJim Miller    private float mX = 0.0f;
393060421045d4d9e411797f91bb509824b03e33fbJim Miller    private float mY = 0.0f;
403060421045d4d9e411797f91bb509824b03e33fbJim Miller    private float mScaleX = 1.0f;
413060421045d4d9e411797f91bb509824b03e33fbJim Miller    private float mScaleY = 1.0f;
423060421045d4d9e411797f91bb509824b03e33fbJim Miller    private BitmapDrawable mDrawable;
433060421045d4d9e411797f91bb509824b03e33fbJim Miller    private float mAlpha = 1f;
442794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    private ArrayList<ObjectAnimator> mAnimators = new ArrayList<ObjectAnimator>();
452794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    private ArrayList<ObjectAnimator> mNeedToStart = new ArrayList<ObjectAnimator>();
463060421045d4d9e411797f91bb509824b03e33fbJim Miller
473060421045d4d9e411797f91bb509824b03e33fbJim Miller    public DrawableHolder(BitmapDrawable drawable) {
483060421045d4d9e411797f91bb509824b03e33fbJim Miller        this(drawable, 0.0f, 0.0f);
493060421045d4d9e411797f91bb509824b03e33fbJim Miller    }
503060421045d4d9e411797f91bb509824b03e33fbJim Miller
513060421045d4d9e411797f91bb509824b03e33fbJim Miller    public DrawableHolder(BitmapDrawable drawable, float x, float y) {
523060421045d4d9e411797f91bb509824b03e33fbJim Miller        mDrawable = drawable;
533060421045d4d9e411797f91bb509824b03e33fbJim Miller        mX = x;
543060421045d4d9e411797f91bb509824b03e33fbJim Miller        mY = y;
553060421045d4d9e411797f91bb509824b03e33fbJim Miller        mDrawable.getPaint().setAntiAlias(true); // Force AA
563060421045d4d9e411797f91bb509824b03e33fbJim Miller        mDrawable.setBounds(0, 0, mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight());
573060421045d4d9e411797f91bb509824b03e33fbJim Miller    }
583060421045d4d9e411797f91bb509824b03e33fbJim Miller
593060421045d4d9e411797f91bb509824b03e33fbJim Miller    /**
603060421045d4d9e411797f91bb509824b03e33fbJim Miller     *
613060421045d4d9e411797f91bb509824b03e33fbJim Miller     * Adds an animation that interpolates given property from its current value
623060421045d4d9e411797f91bb509824b03e33fbJim Miller     * to the given value.
633060421045d4d9e411797f91bb509824b03e33fbJim Miller     *
643060421045d4d9e411797f91bb509824b03e33fbJim Miller     * @param duration the duration, in ms.
653060421045d4d9e411797f91bb509824b03e33fbJim Miller     * @param delay the delay to start the animation, in ms.
663060421045d4d9e411797f91bb509824b03e33fbJim Miller     * @param property the property to animate
673060421045d4d9e411797f91bb509824b03e33fbJim Miller     * @param toValue the target value
683060421045d4d9e411797f91bb509824b03e33fbJim Miller     * @param replace if true, replace the current animation with this one.
693060421045d4d9e411797f91bb509824b03e33fbJim Miller     */
702794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    public ObjectAnimator addAnimTo(long duration, long delay,
713060421045d4d9e411797f91bb509824b03e33fbJim Miller            String property, float toValue, boolean replace) {
723060421045d4d9e411797f91bb509824b03e33fbJim Miller
733060421045d4d9e411797f91bb509824b03e33fbJim Miller        if (replace) removeAnimationFor(property);
743060421045d4d9e411797f91bb509824b03e33fbJim Miller
752794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        ObjectAnimator anim = ObjectAnimator.ofFloat(this, property, toValue);
762794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        anim.setDuration(duration);
773060421045d4d9e411797f91bb509824b03e33fbJim Miller        anim.setStartDelay(delay);
783060421045d4d9e411797f91bb509824b03e33fbJim Miller        anim.setInterpolator(EASE_OUT_INTERPOLATOR);
793060421045d4d9e411797f91bb509824b03e33fbJim Miller        this.addAnimation(anim, replace);
803060421045d4d9e411797f91bb509824b03e33fbJim Miller        if (DBG) Log.v(TAG, "animationCount = " + mAnimators.size());
813060421045d4d9e411797f91bb509824b03e33fbJim Miller        return anim;
823060421045d4d9e411797f91bb509824b03e33fbJim Miller    }
833060421045d4d9e411797f91bb509824b03e33fbJim Miller
843060421045d4d9e411797f91bb509824b03e33fbJim Miller    /**
853060421045d4d9e411797f91bb509824b03e33fbJim Miller     * Stops all animations for the given property and removes it from the list.
863060421045d4d9e411797f91bb509824b03e33fbJim Miller     *
873060421045d4d9e411797f91bb509824b03e33fbJim Miller     * @param property
883060421045d4d9e411797f91bb509824b03e33fbJim Miller     */
893060421045d4d9e411797f91bb509824b03e33fbJim Miller    public void removeAnimationFor(String property) {
90e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase        ArrayList<ObjectAnimator> removalList = (ArrayList<ObjectAnimator>)mAnimators.clone();
91e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase        for (ObjectAnimator currentAnim : removalList) {
923060421045d4d9e411797f91bb509824b03e33fbJim Miller            if (property.equals(currentAnim.getPropertyName())) {
933060421045d4d9e411797f91bb509824b03e33fbJim Miller                currentAnim.cancel();
943060421045d4d9e411797f91bb509824b03e33fbJim Miller            }
953060421045d4d9e411797f91bb509824b03e33fbJim Miller        }
963060421045d4d9e411797f91bb509824b03e33fbJim Miller    }
973060421045d4d9e411797f91bb509824b03e33fbJim Miller
983060421045d4d9e411797f91bb509824b03e33fbJim Miller    /**
993060421045d4d9e411797f91bb509824b03e33fbJim Miller     * Stops all animations and removes them from the list.
1003060421045d4d9e411797f91bb509824b03e33fbJim Miller     */
1013060421045d4d9e411797f91bb509824b03e33fbJim Miller    public void clearAnimations() {
1022794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        for (ObjectAnimator currentAnim : mAnimators) {
1033060421045d4d9e411797f91bb509824b03e33fbJim Miller            currentAnim.cancel();
1043060421045d4d9e411797f91bb509824b03e33fbJim Miller        }
1053060421045d4d9e411797f91bb509824b03e33fbJim Miller        mAnimators.clear();
1063060421045d4d9e411797f91bb509824b03e33fbJim Miller    }
1073060421045d4d9e411797f91bb509824b03e33fbJim Miller
1083060421045d4d9e411797f91bb509824b03e33fbJim Miller    /**
1093060421045d4d9e411797f91bb509824b03e33fbJim Miller     * Adds the given animation to the list of animations for this object.
1103060421045d4d9e411797f91bb509824b03e33fbJim Miller     *
1113060421045d4d9e411797f91bb509824b03e33fbJim Miller     * @param anim
1123060421045d4d9e411797f91bb509824b03e33fbJim Miller     * @param overwrite
1133060421045d4d9e411797f91bb509824b03e33fbJim Miller     * @return
1143060421045d4d9e411797f91bb509824b03e33fbJim Miller     */
1152794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    private DrawableHolder addAnimation(ObjectAnimator anim, boolean overwrite) {
1163060421045d4d9e411797f91bb509824b03e33fbJim Miller        if (anim != null)
1173060421045d4d9e411797f91bb509824b03e33fbJim Miller            mAnimators.add(anim);
1183060421045d4d9e411797f91bb509824b03e33fbJim Miller        mNeedToStart.add(anim);
1193060421045d4d9e411797f91bb509824b03e33fbJim Miller        return this;
1203060421045d4d9e411797f91bb509824b03e33fbJim Miller    }
1213060421045d4d9e411797f91bb509824b03e33fbJim Miller
1223060421045d4d9e411797f91bb509824b03e33fbJim Miller    /**
1233060421045d4d9e411797f91bb509824b03e33fbJim Miller     * Draw this object to the canvas using the properties defined in this class.
1243060421045d4d9e411797f91bb509824b03e33fbJim Miller     *
1253060421045d4d9e411797f91bb509824b03e33fbJim Miller     * @param canvas canvas to draw into
1263060421045d4d9e411797f91bb509824b03e33fbJim Miller     */
1273060421045d4d9e411797f91bb509824b03e33fbJim Miller    public void draw(Canvas canvas) {
1283060421045d4d9e411797f91bb509824b03e33fbJim Miller        final float threshold = 1.0f / 256.0f; // contribution less than 1 LSB of RGB byte
1293060421045d4d9e411797f91bb509824b03e33fbJim Miller        if (mAlpha <= threshold) // don't bother if it won't show up
1303060421045d4d9e411797f91bb509824b03e33fbJim Miller            return;
1313060421045d4d9e411797f91bb509824b03e33fbJim Miller        canvas.save(Canvas.MATRIX_SAVE_FLAG);
1323060421045d4d9e411797f91bb509824b03e33fbJim Miller        canvas.translate(mX, mY);
1333060421045d4d9e411797f91bb509824b03e33fbJim Miller        canvas.scale(mScaleX, mScaleY);
1343060421045d4d9e411797f91bb509824b03e33fbJim Miller        canvas.translate(-0.5f*getWidth(), -0.5f*getHeight());
1353060421045d4d9e411797f91bb509824b03e33fbJim Miller        mDrawable.setAlpha((int) Math.round(mAlpha * 255f));
1363060421045d4d9e411797f91bb509824b03e33fbJim Miller        mDrawable.draw(canvas);
1373060421045d4d9e411797f91bb509824b03e33fbJim Miller        canvas.restore();
1383060421045d4d9e411797f91bb509824b03e33fbJim Miller    }
1393060421045d4d9e411797f91bb509824b03e33fbJim Miller
1403060421045d4d9e411797f91bb509824b03e33fbJim Miller    /**
1413060421045d4d9e411797f91bb509824b03e33fbJim Miller     * Starts all animations added since the last call to this function.  Used to synchronize
1423060421045d4d9e411797f91bb509824b03e33fbJim Miller     * animations.
1433060421045d4d9e411797f91bb509824b03e33fbJim Miller     *
1443060421045d4d9e411797f91bb509824b03e33fbJim Miller     * @param listener an optional listener to add to the animations. Typically used to know when
1453060421045d4d9e411797f91bb509824b03e33fbJim Miller     * to invalidate the surface these are being drawn to.
1463060421045d4d9e411797f91bb509824b03e33fbJim Miller     */
1473060421045d4d9e411797f91bb509824b03e33fbJim Miller    public void startAnimations(ValueAnimator.AnimatorUpdateListener listener) {
1483060421045d4d9e411797f91bb509824b03e33fbJim Miller        for (int i = 0; i < mNeedToStart.size(); i++) {
1492794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase            ObjectAnimator anim = mNeedToStart.get(i);
1503060421045d4d9e411797f91bb509824b03e33fbJim Miller            anim.addUpdateListener(listener);
1513060421045d4d9e411797f91bb509824b03e33fbJim Miller            anim.addListener(this);
1523060421045d4d9e411797f91bb509824b03e33fbJim Miller            anim.start();
1533060421045d4d9e411797f91bb509824b03e33fbJim Miller        }
1543060421045d4d9e411797f91bb509824b03e33fbJim Miller        mNeedToStart.clear();
1553060421045d4d9e411797f91bb509824b03e33fbJim Miller    }
1563060421045d4d9e411797f91bb509824b03e33fbJim Miller
1573060421045d4d9e411797f91bb509824b03e33fbJim Miller
158c002fab06d5f6d3c83bb2b89c8ee9a14f6580af3Jim Miller    public void setX(float value) {
1593060421045d4d9e411797f91bb509824b03e33fbJim Miller        mX = value;
1603060421045d4d9e411797f91bb509824b03e33fbJim Miller    }
1613060421045d4d9e411797f91bb509824b03e33fbJim Miller
162c002fab06d5f6d3c83bb2b89c8ee9a14f6580af3Jim Miller    public void setY(float value) {
1633060421045d4d9e411797f91bb509824b03e33fbJim Miller        mY = value;
1643060421045d4d9e411797f91bb509824b03e33fbJim Miller    }
1653060421045d4d9e411797f91bb509824b03e33fbJim Miller
166c002fab06d5f6d3c83bb2b89c8ee9a14f6580af3Jim Miller    public void setScaleX(float value) {
1673060421045d4d9e411797f91bb509824b03e33fbJim Miller        mScaleX = value;
1683060421045d4d9e411797f91bb509824b03e33fbJim Miller    }
1693060421045d4d9e411797f91bb509824b03e33fbJim Miller
170c002fab06d5f6d3c83bb2b89c8ee9a14f6580af3Jim Miller    public void setScaleY(float value) {
1713060421045d4d9e411797f91bb509824b03e33fbJim Miller        mScaleY = value;
1723060421045d4d9e411797f91bb509824b03e33fbJim Miller    }
1733060421045d4d9e411797f91bb509824b03e33fbJim Miller
174c002fab06d5f6d3c83bb2b89c8ee9a14f6580af3Jim Miller    public void setAlpha(float alpha) {
1753060421045d4d9e411797f91bb509824b03e33fbJim Miller        mAlpha = alpha;
1763060421045d4d9e411797f91bb509824b03e33fbJim Miller    }
1773060421045d4d9e411797f91bb509824b03e33fbJim Miller
1783060421045d4d9e411797f91bb509824b03e33fbJim Miller    public float getX() {
1793060421045d4d9e411797f91bb509824b03e33fbJim Miller        return mX;
1803060421045d4d9e411797f91bb509824b03e33fbJim Miller    }
1813060421045d4d9e411797f91bb509824b03e33fbJim Miller
1823060421045d4d9e411797f91bb509824b03e33fbJim Miller    public float getY() {
1833060421045d4d9e411797f91bb509824b03e33fbJim Miller        return mY;
1843060421045d4d9e411797f91bb509824b03e33fbJim Miller    }
1853060421045d4d9e411797f91bb509824b03e33fbJim Miller
1863060421045d4d9e411797f91bb509824b03e33fbJim Miller    public float getScaleX() {
1873060421045d4d9e411797f91bb509824b03e33fbJim Miller        return mScaleX;
1883060421045d4d9e411797f91bb509824b03e33fbJim Miller    }
1893060421045d4d9e411797f91bb509824b03e33fbJim Miller
1903060421045d4d9e411797f91bb509824b03e33fbJim Miller    public float getScaleY() {
1913060421045d4d9e411797f91bb509824b03e33fbJim Miller        return mScaleY;
1923060421045d4d9e411797f91bb509824b03e33fbJim Miller    }
1933060421045d4d9e411797f91bb509824b03e33fbJim Miller
1943060421045d4d9e411797f91bb509824b03e33fbJim Miller    public float getAlpha() {
1953060421045d4d9e411797f91bb509824b03e33fbJim Miller        return mAlpha;
1963060421045d4d9e411797f91bb509824b03e33fbJim Miller    }
1973060421045d4d9e411797f91bb509824b03e33fbJim Miller
1983060421045d4d9e411797f91bb509824b03e33fbJim Miller    public BitmapDrawable getDrawable() {
1993060421045d4d9e411797f91bb509824b03e33fbJim Miller        return mDrawable;
2003060421045d4d9e411797f91bb509824b03e33fbJim Miller    }
2013060421045d4d9e411797f91bb509824b03e33fbJim Miller
2023060421045d4d9e411797f91bb509824b03e33fbJim Miller    public int getWidth() {
2033060421045d4d9e411797f91bb509824b03e33fbJim Miller        return mDrawable.getIntrinsicWidth();
2043060421045d4d9e411797f91bb509824b03e33fbJim Miller    }
2053060421045d4d9e411797f91bb509824b03e33fbJim Miller
2063060421045d4d9e411797f91bb509824b03e33fbJim Miller    public int getHeight() {
2073060421045d4d9e411797f91bb509824b03e33fbJim Miller        return mDrawable.getIntrinsicHeight();
2083060421045d4d9e411797f91bb509824b03e33fbJim Miller    }
2093060421045d4d9e411797f91bb509824b03e33fbJim Miller
2103060421045d4d9e411797f91bb509824b03e33fbJim Miller    public void onAnimationCancel(Animator animation) {
2113060421045d4d9e411797f91bb509824b03e33fbJim Miller
2123060421045d4d9e411797f91bb509824b03e33fbJim Miller    }
2133060421045d4d9e411797f91bb509824b03e33fbJim Miller
2143060421045d4d9e411797f91bb509824b03e33fbJim Miller    public void onAnimationEnd(Animator animation) {
2153060421045d4d9e411797f91bb509824b03e33fbJim Miller        mAnimators.remove(animation);
2163060421045d4d9e411797f91bb509824b03e33fbJim Miller    }
2173060421045d4d9e411797f91bb509824b03e33fbJim Miller
2183060421045d4d9e411797f91bb509824b03e33fbJim Miller    public void onAnimationRepeat(Animator animation) {
2193060421045d4d9e411797f91bb509824b03e33fbJim Miller
2203060421045d4d9e411797f91bb509824b03e33fbJim Miller    }
2213060421045d4d9e411797f91bb509824b03e33fbJim Miller
2223060421045d4d9e411797f91bb509824b03e33fbJim Miller    public void onAnimationStart(Animator animation) {
2233060421045d4d9e411797f91bb509824b03e33fbJim Miller
2243060421045d4d9e411797f91bb509824b03e33fbJim Miller    }
2253060421045d4d9e411797f91bb509824b03e33fbJim Miller}
226