1/*
2 * Copyright (C) 2012 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
17package android.support.v4.widget;
18
19import android.content.Context;
20import android.widget.Scroller;
21
22/**
23 * Provides access to new {@link android.widget.Scroller Scroller} APIs when available.
24 *
25 * <p>This class provides a platform version-independent mechanism for obeying the
26 * current device's preferred scroll physics and fling behavior. It offers a subset of
27 * the APIs from Scroller or OverScroller.</p>
28 */
29class ScrollerCompat {
30    Scroller mScroller;
31
32    static class ScrollerCompatImplIcs extends ScrollerCompat {
33        public ScrollerCompatImplIcs(Context context) {
34            super(context);
35        }
36
37        @Override
38        public float getCurrVelocity() {
39            return ScrollerCompatIcs.getCurrVelocity(mScroller);
40        }
41    }
42
43    public static ScrollerCompat from(Context context) {
44        if (android.os.Build.VERSION.SDK_INT >= 14) {
45            return new ScrollerCompatImplIcs(context);
46        }
47        return new ScrollerCompat(context);
48    }
49
50    ScrollerCompat(Context context) {
51        mScroller = new Scroller(context);
52    }
53
54    /**
55     * Returns whether the scroller has finished scrolling.
56     *
57     * @return True if the scroller has finished scrolling, false otherwise.
58     */
59    public boolean isFinished() {
60        return mScroller.isFinished();
61    }
62
63    /**
64     * Returns how long the scroll event will take, in milliseconds.
65     *
66     * @return The duration of the scroll in milliseconds.
67     */
68    public int getDuration() {
69        return mScroller.getDuration();
70    }
71
72    /**
73     * Returns the current X offset in the scroll.
74     *
75     * @return The new X offset as an absolute distance from the origin.
76     */
77    public int getCurrX() {
78        return mScroller.getCurrX();
79    }
80
81    /**
82     * Returns the current Y offset in the scroll.
83     *
84     * @return The new Y offset as an absolute distance from the origin.
85     */
86    public int getCurrY() {
87        return mScroller.getCurrY();
88    }
89
90    /**
91     * Returns the current velocity.
92     *
93     * TODO: Approximate a sane result for older platform versions. Right now
94     * this will return 0 for platforms earlier than ICS. This is acceptable
95     * at the moment only since it is only used for EdgeEffect, which is also only
96     * present in ICS+, and ScrollerCompat is not public.
97     *
98     * @return The original velocity less the deceleration. Result may be
99     * negative.
100     */
101    public float getCurrVelocity() {
102        return 0;
103    }
104
105    /**
106     * Call this when you want to know the new location.  If it returns true,
107     * the animation is not yet finished.  loc will be altered to provide the
108     * new location.
109     */
110    public boolean computeScrollOffset() {
111        return mScroller.computeScrollOffset();
112    }
113
114    /**
115     * Start scrolling by providing a starting point and the distance to travel.
116     * The scroll will use the default value of 250 milliseconds for the
117     * duration.
118     *
119     * @param startX Starting horizontal scroll offset in pixels. Positive
120     *        numbers will scroll the content to the left.
121     * @param startY Starting vertical scroll offset in pixels. Positive numbers
122     *        will scroll the content up.
123     * @param dx Horizontal distance to travel. Positive numbers will scroll the
124     *        content to the left.
125     * @param dy Vertical distance to travel. Positive numbers will scroll the
126     *        content up.
127     */
128    public void startScroll(int startX, int startY, int dx, int dy) {
129        mScroller.startScroll(startX, startY, dx, dy);
130    }
131
132    /**
133     * Start scrolling by providing a starting point and the distance to travel.
134     *
135     * @param startX Starting horizontal scroll offset in pixels. Positive
136     *        numbers will scroll the content to the left.
137     * @param startY Starting vertical scroll offset in pixels. Positive numbers
138     *        will scroll the content up.
139     * @param dx Horizontal distance to travel. Positive numbers will scroll the
140     *        content to the left.
141     * @param dy Vertical distance to travel. Positive numbers will scroll the
142     *        content up.
143     * @param duration Duration of the scroll in milliseconds.
144     */
145    public void startScroll(int startX, int startY, int dx, int dy, int duration) {
146        mScroller.startScroll(startX, startY, dx, dy, duration);
147    }
148
149    /**
150     * Start scrolling based on a fling gesture. The distance travelled will
151     * depend on the initial velocity of the fling.
152     *
153     * @param startX Starting point of the scroll (X)
154     * @param startY Starting point of the scroll (Y)
155     * @param velocityX Initial velocity of the fling (X) measured in pixels per
156     *        second.
157     * @param velocityY Initial velocity of the fling (Y) measured in pixels per
158     *        second
159     * @param minX Minimum X value. The scroller will not scroll past this
160     *        point.
161     * @param maxX Maximum X value. The scroller will not scroll past this
162     *        point.
163     * @param minY Minimum Y value. The scroller will not scroll past this
164     *        point.
165     * @param maxY Maximum Y value. The scroller will not scroll past this
166     *        point.
167     */
168    public void fling(int startX, int startY, int velocityX, int velocityY,
169            int minX, int maxX, int minY, int maxY) {
170        mScroller.fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY);
171    }
172
173    /**
174     * Stops the animation. Contrary to {@link #forceFinished(boolean)},
175     * aborting the animating cause the scroller to move to the final x and y
176     * position
177     */
178    public void abortAnimation() {
179        mScroller.abortAnimation();
180    }
181}
182