am 62ea9554: Merge "Temporary drawable for Quantum progress indicator" into lmp-preview-dev

* commit '62ea9554753820df25343e52e0dcab090e5755b5':
  Temporary drawable for Quantum progress indicator
diff --git a/core/res/res/drawable-hdpi/spinner_20_inner_holo.png b/core/res/res/drawable-hdpi/spinner_20_inner_holo.png
deleted file mode 100644
index 49841ea..0000000
--- a/core/res/res/drawable-hdpi/spinner_20_inner_holo.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_20_outer_holo.png b/core/res/res/drawable-hdpi/spinner_20_outer_holo.png
deleted file mode 100644
index 69f0070..0000000
--- a/core/res/res/drawable-hdpi/spinner_20_outer_holo.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_20_inner_holo.png b/core/res/res/drawable-mdpi/spinner_20_inner_holo.png
deleted file mode 100644
index 4569fae..0000000
--- a/core/res/res/drawable-mdpi/spinner_20_inner_holo.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_20_outer_holo.png b/core/res/res/drawable-mdpi/spinner_20_outer_holo.png
deleted file mode 100644
index 9287dd7..0000000
--- a/core/res/res/drawable-mdpi/spinner_20_outer_holo.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_20_inner_holo.png b/core/res/res/drawable-xhdpi/spinner_20_inner_holo.png
deleted file mode 100644
index 76e9428..0000000
--- a/core/res/res/drawable-xhdpi/spinner_20_inner_holo.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_20_outer_holo.png b/core/res/res/drawable-xhdpi/spinner_20_outer_holo.png
deleted file mode 100644
index 6f693d6..0000000
--- a/core/res/res/drawable-xhdpi/spinner_20_outer_holo.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_20_inner_holo.png b/core/res/res/drawable-xxhdpi/spinner_20_inner_holo.png
deleted file mode 100644
index 6cbd1f4..0000000
--- a/core/res/res/drawable-xxhdpi/spinner_20_inner_holo.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_20_outer_holo.png b/core/res/res/drawable-xxhdpi/spinner_20_outer_holo.png
deleted file mode 100644
index b6af5e7..0000000
--- a/core/res/res/drawable-xxhdpi/spinner_20_outer_holo.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable/progress_large_quantum.xml b/core/res/res/drawable/progress_large_quantum.xml
new file mode 100644
index 0000000..7bef637
--- /dev/null
+++ b/core/res/res/drawable/progress_large_quantum.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<quantum-progress xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="?attr/colorControlActivated"
+    android:width="76dp"
+    android:height="76dp"
+    android:thickness="6.3dp"
+    android:innerRadius="30.1dp" />
diff --git a/core/res/res/drawable/progress_medium_quantum.xml b/core/res/res/drawable/progress_medium_quantum.xml
new file mode 100644
index 0000000..adc72f0
--- /dev/null
+++ b/core/res/res/drawable/progress_medium_quantum.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<quantum-progress xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="?attr/colorControlActivated"
+    android:width="48dp"
+    android:height="48dp"
+    android:thickness="4dp"
+    android:innerRadius="19dp" />
diff --git a/core/res/res/drawable/progress_small_quantum.xml b/core/res/res/drawable/progress_small_quantum.xml
new file mode 100644
index 0000000..eb4884a
--- /dev/null
+++ b/core/res/res/drawable/progress_small_quantum.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<quantum-progress xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="?attr/colorControlActivated"
+    android:width="16dp"
+    android:height="16dp"
+    android:thickness="1.3dp"
+    android:innerRadius="6.3dp" />
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 089e424..3b6c1bd 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4562,6 +4562,16 @@
         <attr name="drawable" />
     </declare-styleable>
 
+    <!-- Drawable used to render the Quantum progress indicator. -->
+    <declare-styleable name="QuantumProgressDrawable">
+        <attr name="visible" />
+        <attr name="thickness" />
+        <attr name="innerRadius" />
+        <attr name="width" />
+        <attr name="height" />
+        <attr name="color" />
+    </declare-styleable>
+
     <declare-styleable name="InsetDrawable">
         <attr name="visible" />
         <attr name="drawable" />
diff --git a/core/res/res/values/styles_quantum.xml b/core/res/res/values/styles_quantum.xml
index 8c2e14e..cc8be67 100644
--- a/core/res/res/values/styles_quantum.xml
+++ b/core/res/res/values/styles_quantum.xml
@@ -547,7 +547,7 @@
     </style>
 
     <style name="Widget.Quantum.ProgressBar" parent="Widget.ProgressBar">
-        <item name="indeterminateDrawable">@drawable/progress_medium_holo</item>
+        <item name="indeterminateDrawable">@drawable/progress_medium_quantum</item>
     </style>
 
     <style name="Widget.Quantum.ProgressBar.Inverse"/>
@@ -560,14 +560,14 @@
     </style>
 
     <style name="Widget.Quantum.ProgressBar.Small" parent="Widget.ProgressBar.Small">
-        <item name="indeterminateDrawable">@drawable/progress_small_holo</item>
+        <item name="indeterminateDrawable">@drawable/progress_small_quantum</item>
     </style>
 
     <style name="Widget.Quantum.ProgressBar.Small.Inverse"/>
     <style name="Widget.Quantum.ProgressBar.Small.Title"/>
 
     <style name="Widget.Quantum.ProgressBar.Large" parent="Widget.ProgressBar.Large">
-        <item name="indeterminateDrawable">@drawable/progress_large_holo</item>
+        <item name="indeterminateDrawable">@drawable/progress_large_quantum</item>
     </style>
 
     <style name="Widget.Quantum.ProgressBar.Large.Inverse"/>
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 76dd1c8..3a32e80 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -1023,6 +1023,9 @@
             drawable = new StateListDrawable();
         } else if (name.equals("animated-selector")) {
             drawable = new AnimatedStateListDrawable();
+        } else if (name.equals("quantum-progress")) {
+            // TODO: Replace this with something less ridiculous.
+            drawable = new QuantumProgressDrawable();
         } else if (name.equals("level-list")) {
             drawable = new LevelListDrawable();
         } else if (name.equals("layer-list")) {
diff --git a/graphics/java/android/graphics/drawable/QuantumProgressDrawable.java b/graphics/java/android/graphics/drawable/QuantumProgressDrawable.java
new file mode 100644
index 0000000..d756eb1
--- /dev/null
+++ b/graphics/java/android/graphics/drawable/QuantumProgressDrawable.java
@@ -0,0 +1,491 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.drawable;
+
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.Paint.Cap;
+import android.graphics.Paint.Style;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.LinearInterpolator;
+
+import com.android.internal.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+/**
+ * Fancy progress indicator for Quantum theme.
+ *
+ * TODO: Replace this class with something less ridiculous.
+ */
+class QuantumProgressDrawable extends Drawable implements Animatable {
+    private static final TimeInterpolator LINEAR_INTERPOLATOR = new LinearInterpolator();
+    private static final TimeInterpolator END_CURVE_INTERPOLATOR = new EndCurveInterpolator();
+    private static final TimeInterpolator START_CURVE_INTERPOLATOR = new StartCurveInterpolator();
+
+    /** The list of animators operating on this drawable. */
+    private final ArrayList<Animator> mAnimators = new ArrayList<Animator>();
+
+    /** The indicator ring, used to manage animation state. */
+    private final Ring mRing;
+
+    private QuantumProgressState mState;
+
+    private boolean mMutated;
+
+    public QuantumProgressDrawable() {
+        this(new QuantumProgressState(null), null);
+    }
+
+    private QuantumProgressDrawable(QuantumProgressState state, Theme theme) {
+        mState = state;
+        if (theme != null && state.canApplyTheme()) {
+            applyTheme(theme);
+        }
+
+        mRing = new Ring(mCallback);
+        mMutated = false;
+
+        initializeFromState();
+        setupAnimators();
+    }
+
+    private void initializeFromState() {
+        final QuantumProgressState state = mState;
+
+        final Ring ring = mRing;
+        ring.setStrokeWidth(state.mStrokeWidth);
+
+        final int color = state.mColor.getColorForState(getState(), Color.TRANSPARENT);
+        ring.setColor(color);
+
+        final float minEdge = Math.min(state.mWidth, state.mHeight);
+        if (state.mInnerRadius <= 0 || minEdge < 0) {
+            ring.setInsets((int) Math.ceil(state.mStrokeWidth / 2.0f));
+        } else {
+            float insets = minEdge / 2.0f - state.mInnerRadius;
+            ring.setInsets(insets);
+        }
+    }
+
+    @Override
+    public Drawable mutate() {
+        if (!mMutated && super.mutate() == this) {
+            mState = new QuantumProgressState(mState);
+            mMutated = true;
+        }
+        return this;
+    }
+
+    @Override
+    protected boolean onStateChange(int[] state) {
+        boolean changed = super.onStateChange(state);
+
+        final int color = mState.mColor.getColorForState(state, Color.TRANSPARENT);
+        if (color != mRing.getColor()) {
+            mRing.setColor(color);
+            changed = true;
+        }
+
+        return changed;
+    }
+
+    @Override
+    public boolean isStateful() {
+        return super.isStateful() || mState.mColor.isStateful();
+    }
+
+    @Override
+    public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
+            throws XmlPullParserException, IOException {
+        final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.QuantumProgressDrawable);
+        super.inflateWithAttributes(r, parser, a, R.styleable.QuantumProgressDrawable_visible);
+        updateStateFromTypedArray(a);
+        a.recycle();
+
+        initializeFromState();
+    }
+
+    @Override
+    public void applyTheme(Theme t) {
+        final TypedArray a = t.resolveAttributes(mState.mThemeAttrs,
+                R.styleable.QuantumProgressDrawable);
+        updateStateFromTypedArray(a);
+        a.recycle();
+    }
+
+    private void updateStateFromTypedArray(TypedArray a) {
+        final QuantumProgressState state = mState;
+        state.mThemeAttrs = a.extractThemeAttrs();
+        state.mWidth = a.getDimensionPixelSize(
+                R.styleable.QuantumProgressDrawable_width, state.mWidth);
+        state.mHeight = a.getDimensionPixelSize(
+                R.styleable.QuantumProgressDrawable_height, state.mHeight);
+        state.mInnerRadius = a.getDimension(
+                R.styleable.QuantumProgressDrawable_innerRadius, state.mInnerRadius);
+        state.mStrokeWidth = a.getDimension(
+                R.styleable.QuantumProgressDrawable_thickness, state.mStrokeWidth);
+
+        if (a.hasValue(R.styleable.QuantumProgressDrawable_color)) {
+            state.mColor = a.getColorStateList(R.styleable.QuantumProgressDrawable_color);
+        }
+    }
+
+    @Override
+    public boolean setVisible(boolean visible, boolean restart) {
+        boolean changed = super.setVisible(visible, restart);
+        if (visible) {
+            if (changed || restart) {
+                start();
+            }
+        } else {
+            stop();
+        }
+        return changed;
+    }
+
+    @Override
+    public int getIntrinsicHeight() {
+        return mState.mHeight;
+    }
+
+    @Override
+    public int getIntrinsicWidth() {
+        return mState.mWidth;
+    }
+
+    @Override
+    public void draw(Canvas c) {
+        mRing.draw(c, getBounds());
+    }
+
+    @Override
+    public void setAlpha(int alpha) {
+        mRing.setAlpha(alpha);
+    }
+
+    @Override
+    public int getAlpha() {
+        return mRing.getAlpha();
+    }
+
+    @Override
+    public void setColorFilter(ColorFilter colorFilter) {
+        mRing.setColorFilter(colorFilter);
+    }
+
+    @Override
+    public ColorFilter getColorFilter() {
+        return mRing.getColorFilter();
+    }
+
+    @Override
+    public int getOpacity() {
+        return PixelFormat.TRANSLUCENT;
+    }
+
+    @Override
+    public boolean isRunning() {
+        final ArrayList<Animator> animators = mAnimators;
+        final int N = animators.size();
+        for (int i = 0; i < N; i++) {
+            final Animator animator = animators.get(i);
+            if (animator.isRunning()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public void start() {
+        final ArrayList<Animator> animators = mAnimators;
+        final int N = animators.size();
+        for (int i = 0; i < N; i++) {
+            final Animator animator = animators.get(i);
+            if (animator.isPaused()) {
+                animator.resume();
+            } else if (!animator.isRunning()){
+                animator.start();
+            }
+        }
+    }
+
+    @Override
+    public void stop() {
+        final ArrayList<Animator> animators = mAnimators;
+        final int N = animators.size();
+        for (int i = 0; i < N; i++) {
+            final Animator animator = animators.get(i);
+            animator.pause();
+        }
+    }
+
+    private void setupAnimators() {
+        final Ring ring = mRing;
+
+        final ObjectAnimator endTrim = ObjectAnimator.ofFloat(ring, "endTrim", 0, 0.75f);
+        endTrim.setDuration(1000 * 80 / 60);
+        endTrim.setInterpolator(START_CURVE_INTERPOLATOR);
+        endTrim.setRepeatCount(ObjectAnimator.INFINITE);
+        endTrim.setRepeatMode(ObjectAnimator.RESTART);
+
+        final ObjectAnimator startTrim = ObjectAnimator.ofFloat(ring, "startTrim", 0.0f, 0.75f);
+        startTrim.setDuration(1000 * 80 / 60);
+        startTrim.setInterpolator(END_CURVE_INTERPOLATOR);
+        startTrim.setRepeatCount(ObjectAnimator.INFINITE);
+        startTrim.setRepeatMode(ObjectAnimator.RESTART);
+
+        final ObjectAnimator rotation = ObjectAnimator.ofFloat(ring, "rotation", 0.0f, 0.25f);
+        rotation.setDuration(1000 * 80 / 60);
+        rotation.setInterpolator(LINEAR_INTERPOLATOR);
+        rotation.setRepeatCount(ObjectAnimator.INFINITE);
+        rotation.setRepeatMode(ObjectAnimator.RESTART);
+
+        mAnimators.add(endTrim);
+        mAnimators.add(startTrim);
+        mAnimators.add(rotation);
+    }
+
+    private final Callback mCallback = new Callback() {
+        @Override
+        public void invalidateDrawable(Drawable d) {
+            invalidateSelf();
+        }
+
+        @Override
+        public void scheduleDrawable(Drawable d, Runnable what, long when) {
+            scheduleSelf(what, when);
+        }
+
+        @Override
+        public void unscheduleDrawable(Drawable d, Runnable what) {
+            unscheduleSelf(what);
+        }
+    };
+
+    private static class QuantumProgressState extends ConstantState {
+        private int[] mThemeAttrs = null;
+        private float mStrokeWidth = 5.0f;
+        private float mInnerRadius = -1.0f;
+        private int mWidth = -1;
+        private int mHeight = -1;
+        private ColorStateList mColor = ColorStateList.valueOf(Color.TRANSPARENT);
+
+        public QuantumProgressState(QuantumProgressState orig) {
+            if (orig != null) {
+                mThemeAttrs = orig.mThemeAttrs;
+                mStrokeWidth = orig.mStrokeWidth;
+                mInnerRadius = orig.mInnerRadius;
+                mWidth = orig.mWidth;
+                mHeight = orig.mHeight;
+                mColor = orig.mColor;
+            }
+        }
+
+        @Override
+        public boolean canApplyTheme() {
+            return mThemeAttrs != null;
+        }
+
+        @Override
+        public Drawable newDrawable() {
+            return newDrawable(null, null);
+        }
+
+        @Override
+        public Drawable newDrawable(Resources res) {
+            return newDrawable(res, null);
+        }
+
+        @Override
+        public Drawable newDrawable(Resources res, Theme theme) {
+            return new QuantumProgressDrawable(this, theme);
+        }
+
+        @Override
+        public int getChangingConfigurations() {
+            return 0;
+        }
+    }
+
+    private static class Ring {
+        private final RectF mTempBounds = new RectF();
+        private final Paint mPaint = new Paint();
+
+        private final Callback mCallback;
+
+        private float mStartTrim = 0.0f;
+        private float mEndTrim = 0.0f;
+        private float mRotation = 0.0f;
+        private float mStrokeWidth = 5.0f;
+        private float mStrokeInset = 2.5f;
+
+        private int mAlpha = 0xFF;
+        private int mColor = Color.BLACK;
+
+        public Ring(Callback callback) {
+            mCallback = callback;
+
+            mPaint.setStrokeCap(Cap.ROUND);
+            mPaint.setAntiAlias(true);
+            mPaint.setStyle(Style.STROKE);
+        }
+
+        public void draw(Canvas c, Rect bounds) {
+            final RectF arcBounds = mTempBounds;
+            arcBounds.set(bounds);
+            arcBounds.inset(mStrokeInset, mStrokeInset);
+
+            final float startAngle = (mStartTrim + mRotation) * 360;
+            final float endAngle = (mEndTrim + mRotation) * 360;
+            float sweepAngle = endAngle - startAngle;
+
+            // Ensure the sweep angle isn't too small to draw.
+            final float diameter = Math.min(arcBounds.width(), arcBounds.height());
+            final float minAngle = (float) (360.0 / (diameter * Math.PI));
+            if (sweepAngle < minAngle && sweepAngle > -minAngle) {
+                sweepAngle = Math.signum(sweepAngle) * minAngle;
+            }
+
+            c.drawArc(arcBounds, startAngle, sweepAngle, false, mPaint);
+        }
+
+        public void setColorFilter(ColorFilter filter) {
+            mPaint.setColorFilter(filter);
+            invalidateSelf();
+        }
+
+        public ColorFilter getColorFilter() {
+            return mPaint.getColorFilter();
+        }
+
+        public void setAlpha(int alpha) {
+            mAlpha = alpha;
+            mPaint.setColor(mColor & 0xFFFFFF | alpha << 24);
+            invalidateSelf();
+        }
+
+        public int getAlpha() {
+            return mAlpha;
+        }
+
+        public void setColor(int color) {
+            mColor = color;
+            mPaint.setColor(color & 0xFFFFFF | mAlpha << 24);
+            invalidateSelf();
+        }
+
+        public int getColor() {
+            return mColor;
+        }
+
+        public void setStrokeWidth(float strokeWidth) {
+            mStrokeWidth = strokeWidth;
+            mPaint.setStrokeWidth(strokeWidth);
+            invalidateSelf();
+        }
+
+        @SuppressWarnings("unused")
+        public float getStrokeWidth() {
+            return mStrokeWidth;
+        }
+
+        @SuppressWarnings("unused")
+        public void setStartTrim(float startTrim) {
+            mStartTrim = startTrim;
+            invalidateSelf();
+        }
+
+        @SuppressWarnings("unused")
+        public float getStartTrim() {
+            return mStartTrim;
+        }
+
+        @SuppressWarnings("unused")
+        public void setEndTrim(float endTrim) {
+            mEndTrim = endTrim;
+            invalidateSelf();
+        }
+
+        @SuppressWarnings("unused")
+        public float getEndTrim() {
+            return mEndTrim;
+        }
+
+        @SuppressWarnings("unused")
+        public void setRotation(float rotation) {
+            mRotation = rotation;
+            invalidateSelf();
+        }
+
+        @SuppressWarnings("unused")
+        public float getRotation() {
+            return mRotation;
+        }
+
+        public void setInsets(float insets) {
+            mStrokeInset = insets;
+        }
+
+        @SuppressWarnings("unused")
+        public float getInsets() {
+            return mStrokeInset;
+        }
+
+        private void invalidateSelf() {
+            mCallback.invalidateDrawable(null);
+        }
+    }
+
+    /**
+     * Squishes the interpolation curve into the second half of the animation.
+     */
+    private static class EndCurveInterpolator extends AccelerateDecelerateInterpolator {
+        @Override
+        public float getInterpolation(float input) {
+            return super.getInterpolation(Math.max(0, (input - 0.5f) * 2.0f));
+        }
+    }
+
+    /**
+     * Squishes the interpolation curve into the first half of the animation.
+     */
+    private static class StartCurveInterpolator extends AccelerateDecelerateInterpolator {
+        @Override
+        public float getInterpolation(float input) {
+            return super.getInterpolation(Math.min(1, input * 2.0f));
+        }
+    }
+}