1794457ae5cd91d59be97250a347586dc0f24a949Jason Monk/*
2794457ae5cd91d59be97250a347586dc0f24a949Jason Monk * Copyright (C) 2016 The Android Open Source Project
3794457ae5cd91d59be97250a347586dc0f24a949Jason Monk *
4794457ae5cd91d59be97250a347586dc0f24a949Jason Monk * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5794457ae5cd91d59be97250a347586dc0f24a949Jason Monk * except in compliance with the License. You may obtain a copy of the License at
6794457ae5cd91d59be97250a347586dc0f24a949Jason Monk *
7794457ae5cd91d59be97250a347586dc0f24a949Jason Monk *      http://www.apache.org/licenses/LICENSE-2.0
8794457ae5cd91d59be97250a347586dc0f24a949Jason Monk *
9794457ae5cd91d59be97250a347586dc0f24a949Jason Monk * Unless required by applicable law or agreed to in writing, software distributed under the
10794457ae5cd91d59be97250a347586dc0f24a949Jason Monk * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11794457ae5cd91d59be97250a347586dc0f24a949Jason Monk * KIND, either express or implied. See the License for the specific language governing
12794457ae5cd91d59be97250a347586dc0f24a949Jason Monk * permissions and limitations under the License.
13794457ae5cd91d59be97250a347586dc0f24a949Jason Monk */
14794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
15794457ae5cd91d59be97250a347586dc0f24a949Jason Monkpackage com.android.systemui.qs;
16794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
17fa0f47a95d4d5de5900ba2c75c80d725b2bbeeceJason Monkimport android.util.FloatProperty;
18794457ae5cd91d59be97250a347586dc0f24a949Jason Monkimport android.util.MathUtils;
19794457ae5cd91d59be97250a347586dc0f24a949Jason Monkimport android.util.Property;
208d1253e944f47db05a4400793774e7871a28dd73Jason Monkimport android.view.View;
21794457ae5cd91d59be97250a347586dc0f24a949Jason Monkimport android.view.animation.Interpolator;
22794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
23794457ae5cd91d59be97250a347586dc0f24a949Jason Monkimport java.util.ArrayList;
24794457ae5cd91d59be97250a347586dc0f24a949Jason Monkimport java.util.List;
25794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
26794457ae5cd91d59be97250a347586dc0f24a949Jason Monk/**
27794457ae5cd91d59be97250a347586dc0f24a949Jason Monk * Helper class, that handles similar properties as animators (delay, interpolators)
28794457ae5cd91d59be97250a347586dc0f24a949Jason Monk * but can have a float input as to the amount they should be in effect.  This allows
29794457ae5cd91d59be97250a347586dc0f24a949Jason Monk * easier animation that tracks input.
30794457ae5cd91d59be97250a347586dc0f24a949Jason Monk *
31794457ae5cd91d59be97250a347586dc0f24a949Jason Monk * All "delays" and "times" are as fractions from 0-1.
32794457ae5cd91d59be97250a347586dc0f24a949Jason Monk */
33794457ae5cd91d59be97250a347586dc0f24a949Jason Monkpublic class TouchAnimator {
34794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
35794457ae5cd91d59be97250a347586dc0f24a949Jason Monk    private final Object[] mTargets;
36794457ae5cd91d59be97250a347586dc0f24a949Jason Monk    private final KeyframeSet[] mKeyframeSets;
37794457ae5cd91d59be97250a347586dc0f24a949Jason Monk    private final float mStartDelay;
38794457ae5cd91d59be97250a347586dc0f24a949Jason Monk    private final float mEndDelay;
39794457ae5cd91d59be97250a347586dc0f24a949Jason Monk    private final float mSpan;
40794457ae5cd91d59be97250a347586dc0f24a949Jason Monk    private final Interpolator mInterpolator;
41794457ae5cd91d59be97250a347586dc0f24a949Jason Monk    private final Listener mListener;
42df5459daaa0f61f9c15d17f45a547420cdf83ae6Jason Monk    private float mLastT = -1;
43794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
44e80654bf7f3fc817e93d52bea7907a260cf036a2Jason Monk    private TouchAnimator(Object[] targets, KeyframeSet[] keyframeSets,
45794457ae5cd91d59be97250a347586dc0f24a949Jason Monk            float startDelay, float endDelay, Interpolator interpolator, Listener listener) {
46794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        mTargets = targets;
47794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        mKeyframeSets = keyframeSets;
48794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        mStartDelay = startDelay;
49794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        mEndDelay = endDelay;
50794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        mSpan = (1 - mEndDelay - mStartDelay);
51794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        mInterpolator = interpolator;
52794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        mListener = listener;
53794457ae5cd91d59be97250a347586dc0f24a949Jason Monk    }
54794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
55794457ae5cd91d59be97250a347586dc0f24a949Jason Monk    public void setPosition(float fraction) {
56794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        float t = MathUtils.constrain((fraction - mStartDelay) / mSpan, 0, 1);
57794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        if (mInterpolator != null) {
58794457ae5cd91d59be97250a347586dc0f24a949Jason Monk            t = mInterpolator.getInterpolation(t);
59794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        }
60df5459daaa0f61f9c15d17f45a547420cdf83ae6Jason Monk        if (t == mLastT) {
61df5459daaa0f61f9c15d17f45a547420cdf83ae6Jason Monk            return;
62df5459daaa0f61f9c15d17f45a547420cdf83ae6Jason Monk        }
63794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        if (mListener != null) {
64df5459daaa0f61f9c15d17f45a547420cdf83ae6Jason Monk            if (t == 1) {
65794457ae5cd91d59be97250a347586dc0f24a949Jason Monk                mListener.onAnimationAtEnd();
66794457ae5cd91d59be97250a347586dc0f24a949Jason Monk            } else if (t == 0) {
67794457ae5cd91d59be97250a347586dc0f24a949Jason Monk                mListener.onAnimationAtStart();
68df5459daaa0f61f9c15d17f45a547420cdf83ae6Jason Monk            } else if (mLastT <= 0 || mLastT == 1) {
69df5459daaa0f61f9c15d17f45a547420cdf83ae6Jason Monk                mListener.onAnimationStarted();
70794457ae5cd91d59be97250a347586dc0f24a949Jason Monk            }
71794457ae5cd91d59be97250a347586dc0f24a949Jason Monk            mLastT = t;
72794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        }
73794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        for (int i = 0; i < mTargets.length; i++) {
74e80654bf7f3fc817e93d52bea7907a260cf036a2Jason Monk            mKeyframeSets[i].setValue(t, mTargets[i]);
75794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        }
76794457ae5cd91d59be97250a347586dc0f24a949Jason Monk    }
77794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
78fa0f47a95d4d5de5900ba2c75c80d725b2bbeeceJason Monk    private static final FloatProperty<TouchAnimator> POSITION =
79fa0f47a95d4d5de5900ba2c75c80d725b2bbeeceJason Monk            new FloatProperty<TouchAnimator>("position") {
80fa0f47a95d4d5de5900ba2c75c80d725b2bbeeceJason Monk        @Override
81fa0f47a95d4d5de5900ba2c75c80d725b2bbeeceJason Monk        public void setValue(TouchAnimator touchAnimator, float value) {
82fa0f47a95d4d5de5900ba2c75c80d725b2bbeeceJason Monk            touchAnimator.setPosition(value);
83fa0f47a95d4d5de5900ba2c75c80d725b2bbeeceJason Monk        }
84fa0f47a95d4d5de5900ba2c75c80d725b2bbeeceJason Monk
85fa0f47a95d4d5de5900ba2c75c80d725b2bbeeceJason Monk        @Override
86fa0f47a95d4d5de5900ba2c75c80d725b2bbeeceJason Monk        public Float get(TouchAnimator touchAnimator) {
87fa0f47a95d4d5de5900ba2c75c80d725b2bbeeceJason Monk            return touchAnimator.mLastT;
88fa0f47a95d4d5de5900ba2c75c80d725b2bbeeceJason Monk        }
89fa0f47a95d4d5de5900ba2c75c80d725b2bbeeceJason Monk    };
90fa0f47a95d4d5de5900ba2c75c80d725b2bbeeceJason Monk
91794457ae5cd91d59be97250a347586dc0f24a949Jason Monk    public static class ListenerAdapter implements Listener {
92794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        @Override
93794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        public void onAnimationAtStart() { }
94794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
95794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        @Override
96794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        public void onAnimationAtEnd() { }
97794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
98794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        @Override
99794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        public void onAnimationStarted() { }
100794457ae5cd91d59be97250a347586dc0f24a949Jason Monk    }
101794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
102794457ae5cd91d59be97250a347586dc0f24a949Jason Monk    public interface Listener {
103794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        /**
104794457ae5cd91d59be97250a347586dc0f24a949Jason Monk         * Called when the animator moves into a position of "0". Start and end delays are
105794457ae5cd91d59be97250a347586dc0f24a949Jason Monk         * taken into account, so this position may cover a range of fractional inputs.
106794457ae5cd91d59be97250a347586dc0f24a949Jason Monk         */
107794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        void onAnimationAtStart();
108794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
109794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        /**
110794457ae5cd91d59be97250a347586dc0f24a949Jason Monk         * Called when the animator moves into a position of "0". Start and end delays are
111794457ae5cd91d59be97250a347586dc0f24a949Jason Monk         * taken into account, so this position may cover a range of fractional inputs.
112794457ae5cd91d59be97250a347586dc0f24a949Jason Monk         */
113794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        void onAnimationAtEnd();
114794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
115794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        /**
116794457ae5cd91d59be97250a347586dc0f24a949Jason Monk         * Called when the animator moves out of the start or end position and is in a transient
117794457ae5cd91d59be97250a347586dc0f24a949Jason Monk         * state.
118794457ae5cd91d59be97250a347586dc0f24a949Jason Monk         */
119794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        void onAnimationStarted();
120794457ae5cd91d59be97250a347586dc0f24a949Jason Monk    }
121794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
122794457ae5cd91d59be97250a347586dc0f24a949Jason Monk    public static class Builder {
123794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        private List<Object> mTargets = new ArrayList<>();
124794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        private List<KeyframeSet> mValues = new ArrayList<>();
125794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
126794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        private float mStartDelay;
127794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        private float mEndDelay;
128794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        private Interpolator mInterpolator;
129794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        private Listener mListener;
130794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
131794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        public Builder addFloat(Object target, String property, float... values) {
132df5459daaa0f61f9c15d17f45a547420cdf83ae6Jason Monk            add(target, KeyframeSet.ofFloat(getProperty(target, property, float.class), values));
133794457ae5cd91d59be97250a347586dc0f24a949Jason Monk            return this;
134794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        }
135794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
136794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        public Builder addInt(Object target, String property, int... values) {
137df5459daaa0f61f9c15d17f45a547420cdf83ae6Jason Monk            add(target, KeyframeSet.ofInt(getProperty(target, property, int.class), values));
138794457ae5cd91d59be97250a347586dc0f24a949Jason Monk            return this;
139794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        }
140794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
141e80654bf7f3fc817e93d52bea7907a260cf036a2Jason Monk        private void add(Object target, KeyframeSet keyframeSet) {
142794457ae5cd91d59be97250a347586dc0f24a949Jason Monk            mTargets.add(target);
143794457ae5cd91d59be97250a347586dc0f24a949Jason Monk            mValues.add(keyframeSet);
144794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        }
145794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
146df5459daaa0f61f9c15d17f45a547420cdf83ae6Jason Monk        private static Property getProperty(Object target, String property, Class<?> cls) {
1478d1253e944f47db05a4400793774e7871a28dd73Jason Monk            if (target instanceof View) {
1488d1253e944f47db05a4400793774e7871a28dd73Jason Monk                switch (property) {
1498d1253e944f47db05a4400793774e7871a28dd73Jason Monk                    case "translationX":
1508d1253e944f47db05a4400793774e7871a28dd73Jason Monk                        return View.TRANSLATION_X;
1518d1253e944f47db05a4400793774e7871a28dd73Jason Monk                    case "translationY":
1528d1253e944f47db05a4400793774e7871a28dd73Jason Monk                        return View.TRANSLATION_Y;
1538d1253e944f47db05a4400793774e7871a28dd73Jason Monk                    case "translationZ":
1548d1253e944f47db05a4400793774e7871a28dd73Jason Monk                        return View.TRANSLATION_Z;
1558d1253e944f47db05a4400793774e7871a28dd73Jason Monk                    case "alpha":
1568d1253e944f47db05a4400793774e7871a28dd73Jason Monk                        return View.ALPHA;
1578d1253e944f47db05a4400793774e7871a28dd73Jason Monk                    case "rotation":
1588d1253e944f47db05a4400793774e7871a28dd73Jason Monk                        return View.ROTATION;
1598d1253e944f47db05a4400793774e7871a28dd73Jason Monk                    case "x":
1608d1253e944f47db05a4400793774e7871a28dd73Jason Monk                        return View.X;
1618d1253e944f47db05a4400793774e7871a28dd73Jason Monk                    case "y":
1628d1253e944f47db05a4400793774e7871a28dd73Jason Monk                        return View.Y;
1638d1253e944f47db05a4400793774e7871a28dd73Jason Monk                    case "scaleX":
1648d1253e944f47db05a4400793774e7871a28dd73Jason Monk                        return View.SCALE_X;
1658d1253e944f47db05a4400793774e7871a28dd73Jason Monk                    case "scaleY":
1668d1253e944f47db05a4400793774e7871a28dd73Jason Monk                        return View.SCALE_Y;
1678d1253e944f47db05a4400793774e7871a28dd73Jason Monk                }
1688d1253e944f47db05a4400793774e7871a28dd73Jason Monk            }
169fa0f47a95d4d5de5900ba2c75c80d725b2bbeeceJason Monk            if (target instanceof TouchAnimator && "position".equals(property)) {
170fa0f47a95d4d5de5900ba2c75c80d725b2bbeeceJason Monk                return POSITION;
171fa0f47a95d4d5de5900ba2c75c80d725b2bbeeceJason Monk            }
172df5459daaa0f61f9c15d17f45a547420cdf83ae6Jason Monk            return Property.of(target.getClass(), cls, property);
1738d1253e944f47db05a4400793774e7871a28dd73Jason Monk        }
1748d1253e944f47db05a4400793774e7871a28dd73Jason Monk
175794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        public Builder setStartDelay(float startDelay) {
176794457ae5cd91d59be97250a347586dc0f24a949Jason Monk            mStartDelay = startDelay;
177794457ae5cd91d59be97250a347586dc0f24a949Jason Monk            return this;
178794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        }
179794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
180794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        public Builder setEndDelay(float endDelay) {
181794457ae5cd91d59be97250a347586dc0f24a949Jason Monk            mEndDelay = endDelay;
182794457ae5cd91d59be97250a347586dc0f24a949Jason Monk            return this;
183794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        }
184794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
185794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        public Builder setInterpolator(Interpolator intepolator) {
186794457ae5cd91d59be97250a347586dc0f24a949Jason Monk            mInterpolator = intepolator;
187794457ae5cd91d59be97250a347586dc0f24a949Jason Monk            return this;
188794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        }
189794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
190794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        public Builder setListener(Listener listener) {
191794457ae5cd91d59be97250a347586dc0f24a949Jason Monk            mListener = listener;
192794457ae5cd91d59be97250a347586dc0f24a949Jason Monk            return this;
193794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        }
194794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
195794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        public TouchAnimator build() {
196794457ae5cd91d59be97250a347586dc0f24a949Jason Monk            return new TouchAnimator(mTargets.toArray(new Object[mTargets.size()]),
197794457ae5cd91d59be97250a347586dc0f24a949Jason Monk                    mValues.toArray(new KeyframeSet[mValues.size()]),
198794457ae5cd91d59be97250a347586dc0f24a949Jason Monk                    mStartDelay, mEndDelay, mInterpolator, mListener);
199794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        }
200794457ae5cd91d59be97250a347586dc0f24a949Jason Monk    }
201794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
202794457ae5cd91d59be97250a347586dc0f24a949Jason Monk    private static abstract class KeyframeSet {
203794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
2048d1253e944f47db05a4400793774e7871a28dd73Jason Monk        private final float mFrameWidth;
2058d1253e944f47db05a4400793774e7871a28dd73Jason Monk        private final int mSize;
206794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
2078d1253e944f47db05a4400793774e7871a28dd73Jason Monk        public KeyframeSet(int size) {
2088d1253e944f47db05a4400793774e7871a28dd73Jason Monk            mSize = size;
2098d1253e944f47db05a4400793774e7871a28dd73Jason Monk            mFrameWidth = 1 / (float) (size - 1);
210794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        }
211794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
212e80654bf7f3fc817e93d52bea7907a260cf036a2Jason Monk        void setValue(float fraction, Object target) {
213794457ae5cd91d59be97250a347586dc0f24a949Jason Monk            int i;
2148d1253e944f47db05a4400793774e7871a28dd73Jason Monk            for (i = 1; i < mSize - 1 && fraction > mFrameWidth; i++);
2158d1253e944f47db05a4400793774e7871a28dd73Jason Monk            float amount = fraction / mFrameWidth;
216e80654bf7f3fc817e93d52bea7907a260cf036a2Jason Monk            interpolate(i, amount, target);
217794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        }
218794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
219e80654bf7f3fc817e93d52bea7907a260cf036a2Jason Monk        protected abstract void interpolate(int index, float amount, Object target);
220794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
221e80654bf7f3fc817e93d52bea7907a260cf036a2Jason Monk        public static KeyframeSet ofInt(Property property, int... values) {
222e80654bf7f3fc817e93d52bea7907a260cf036a2Jason Monk            return new IntKeyframeSet((Property<?, Integer>) property, values);
223794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        }
224794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
225e80654bf7f3fc817e93d52bea7907a260cf036a2Jason Monk        public static KeyframeSet ofFloat(Property property, float... values) {
226e80654bf7f3fc817e93d52bea7907a260cf036a2Jason Monk            return new FloatKeyframeSet((Property<?, Float>) property, values);
227794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        }
228794457ae5cd91d59be97250a347586dc0f24a949Jason Monk    }
229794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
230e80654bf7f3fc817e93d52bea7907a260cf036a2Jason Monk    private static class FloatKeyframeSet<T> extends KeyframeSet {
2318d1253e944f47db05a4400793774e7871a28dd73Jason Monk        private final float[] mValues;
232e80654bf7f3fc817e93d52bea7907a260cf036a2Jason Monk        private final Property<T, Float> mProperty;
2338d1253e944f47db05a4400793774e7871a28dd73Jason Monk
234e80654bf7f3fc817e93d52bea7907a260cf036a2Jason Monk        public FloatKeyframeSet(Property<T, Float> property, float[] values) {
2358d1253e944f47db05a4400793774e7871a28dd73Jason Monk            super(values.length);
236e80654bf7f3fc817e93d52bea7907a260cf036a2Jason Monk            mProperty = property;
2378d1253e944f47db05a4400793774e7871a28dd73Jason Monk            mValues = values;
238794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        }
239794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
240794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        @Override
241e80654bf7f3fc817e93d52bea7907a260cf036a2Jason Monk        protected void interpolate(int index, float amount, Object target) {
2428d1253e944f47db05a4400793774e7871a28dd73Jason Monk            float firstFloat = mValues[index - 1];
2438d1253e944f47db05a4400793774e7871a28dd73Jason Monk            float secondFloat = mValues[index];
244e80654bf7f3fc817e93d52bea7907a260cf036a2Jason Monk            mProperty.set((T) target, firstFloat + (secondFloat - firstFloat) * amount);
245794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        }
246794457ae5cd91d59be97250a347586dc0f24a949Jason Monk    }
247794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
248e80654bf7f3fc817e93d52bea7907a260cf036a2Jason Monk    private static class IntKeyframeSet<T> extends KeyframeSet {
2498d1253e944f47db05a4400793774e7871a28dd73Jason Monk        private final int[] mValues;
250e80654bf7f3fc817e93d52bea7907a260cf036a2Jason Monk        private final Property<T, Integer> mProperty;
2518d1253e944f47db05a4400793774e7871a28dd73Jason Monk
252e80654bf7f3fc817e93d52bea7907a260cf036a2Jason Monk        public IntKeyframeSet(Property<T, Integer> property, int[] values) {
2538d1253e944f47db05a4400793774e7871a28dd73Jason Monk            super(values.length);
254e80654bf7f3fc817e93d52bea7907a260cf036a2Jason Monk            mProperty = property;
2558d1253e944f47db05a4400793774e7871a28dd73Jason Monk            mValues = values;
256794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        }
257794457ae5cd91d59be97250a347586dc0f24a949Jason Monk
258794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        @Override
259e80654bf7f3fc817e93d52bea7907a260cf036a2Jason Monk        protected void interpolate(int index, float amount, Object target) {
2608d1253e944f47db05a4400793774e7871a28dd73Jason Monk            int firstFloat = mValues[index - 1];
2618d1253e944f47db05a4400793774e7871a28dd73Jason Monk            int secondFloat = mValues[index];
262e80654bf7f3fc817e93d52bea7907a260cf036a2Jason Monk            mProperty.set((T) target, (int) (firstFloat + (secondFloat - firstFloat) * amount));
263794457ae5cd91d59be97250a347586dc0f24a949Jason Monk        }
264794457ae5cd91d59be97250a347586dc0f24a949Jason Monk    }
265794457ae5cd91d59be97250a347586dc0f24a949Jason Monk}
266