1 /*
2  * Copyright 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.example.android.interactivechart;
18 
19 import android.content.Context;
20 import android.os.SystemClock;
21 import android.view.animation.DecelerateInterpolator;
22 import android.view.animation.Interpolator;
23 
24 /**
25  * A simple class that animates double-touch zoom gestures. Functionally similar to a {@link
26  * android.widget.Scroller}.
27  */
28 public class Zoomer {
29     /**
30      * The interpolator, used for making zooms animate 'naturally.'
31      */
32     private Interpolator mInterpolator;
33 
34     /**
35      * The total animation duration for a zoom.
36      */
37     private int mAnimationDurationMillis;
38 
39     /**
40      * Whether or not the current zoom has finished.
41      */
42     private boolean mFinished = true;
43 
44     /**
45      * The current zoom value; computed by {@link #computeZoom()}.
46      */
47     private float mCurrentZoom;
48 
49     /**
50      * The time the zoom started, computed using {@link android.os.SystemClock#elapsedRealtime()}.
51      */
52     private long mStartRTC;
53 
54     /**
55      * The destination zoom factor.
56      */
57     private float mEndZoom;
58 
Zoomer(Context context)59     public Zoomer(Context context) {
60         mInterpolator = new DecelerateInterpolator();
61         mAnimationDurationMillis = context.getResources().getInteger(
62                 android.R.integer.config_shortAnimTime);
63     }
64 
65     /**
66      * Forces the zoom finished state to the given value. Unlike {@link #abortAnimation()}, the
67      * current zoom value isn't set to the ending value.
68      *
69      * @see android.widget.Scroller#forceFinished(boolean)
70      */
forceFinished(boolean finished)71     public void forceFinished(boolean finished) {
72         mFinished = finished;
73     }
74 
75     /**
76      * Aborts the animation, setting the current zoom value to the ending value.
77      *
78      * @see android.widget.Scroller#abortAnimation()
79      */
abortAnimation()80     public void abortAnimation() {
81         mFinished = true;
82         mCurrentZoom = mEndZoom;
83     }
84 
85     /**
86      * Starts a zoom from 1.0 to (1.0 + endZoom). That is, to zoom from 100% to 125%, endZoom should
87      * by 0.25f.
88      *
89      * @see android.widget.Scroller#startScroll(int, int, int, int)
90      */
startZoom(float endZoom)91     public void startZoom(float endZoom) {
92         mStartRTC = SystemClock.elapsedRealtime();
93         mEndZoom = endZoom;
94 
95         mFinished = false;
96         mCurrentZoom = 1f;
97     }
98 
99     /**
100      * Computes the current zoom level, returning true if the zoom is still active and false if the
101      * zoom has finished.
102      *
103      * @see android.widget.Scroller#computeScrollOffset()
104      */
computeZoom()105     public boolean computeZoom() {
106         if (mFinished) {
107             return false;
108         }
109 
110         long tRTC = SystemClock.elapsedRealtime() - mStartRTC;
111         if (tRTC >= mAnimationDurationMillis) {
112             mFinished = true;
113             mCurrentZoom = mEndZoom;
114             return false;
115         }
116 
117         float t = tRTC * 1f / mAnimationDurationMillis;
118         mCurrentZoom = mEndZoom * mInterpolator.getInterpolation(t);
119         return true;
120     }
121 
122     /**
123      * Returns the current zoom level.
124      *
125      * @see android.widget.Scroller#getCurrX()
126      */
getCurrZoom()127     public float getCurrZoom() {
128         return mCurrentZoom;
129     }
130 }
131