blob: 955495a367b1bcb6e0f75d5e9d8a1bb246e94df0 [file] [log] [blame]
&& repo sync -j8518edbf2012-11-30 16:28:27 -08001page.title=Animating a Scroll Gesture
2parent.title=Using Touch Gestures
3parent.link=index.html
4
5trainingnavtop=true
6next.title=Handling Multi-Touch Gestures
7next.link=multi.html
8
9@jd:body
10
11<div id="tb-wrapper">
12<div id="tb">
13
14<!-- table of contents -->
15<h2>This lesson teaches you to</h2>
16<ol>
17 <li><a href="#scroll">Implement Touch-Based Scrolling</a></li>
18</ol>
19
20<!-- other docs (NOT javadocs) -->
21<h2>You should also read</h2>
22
23<ul>
24 <li><a href="http://developer.android.com/guide/topics/ui/ui-events.html">Input Events</a> API Guide
25 </li>
26 <li><a href="{@docRoot}guide/topics/sensors/sensors_overview.html">Sensors Overview</a></li>
27 <li><a href="http://android-developers.blogspot.com/2010/06/making-sense-of-multitouch.html">Making Sense of Multitouch</a> blog post</li>
28 <li><a href="{@docRoot}training/custom-views/making-interactive.html">Making the View Interactive</a> </li>
29 <li>Design Guide for <a href="{@docRoot}design/patterns/gestures.html">Gestures</a></li>
30 <li>Design Guide for <a href="{@docRoot}design/style/touch-feedback.html">Touch Feedback</a></li>
31</ul>
32
33
34</div>
35</div>
36
37<p>In Android, scrolling is typically achieved by using the
38{@link android.widget.ScrollView}
39class. Any standard layout that might extend beyond the bounds of its container should be
40nested in a {@link android.widget.ScrollView} to provide a scrollable view that's
41managed by the framework. Implementing a custom scroller should only be
42necessary for special scenarios. This lesson describes such a scenario: displaying
43a scrolling effect in response to touch gestures using <em>scrollers</em>.
44
45
46<p>You can use scrollers ({@link android.widget.Scroller} or {@link
47android.widget.OverScroller}) to collect the data you need to produce a
48scrolling animation in response to a touch event. {@link
49android.widget.Scroller} and {@link android.widget.OverScroller} are largely
50interchangeable&mdash;the difference is that {@link android.widget.OverScroller}
51allows temporarily scrolling beyond the minimum/maximum boundaries and springing
52back to the bounds. This is normally rendered using a "glow" effect, provided by
53the {@link android.widget.EdgeEffect} or {@link
54android.support.v4.widget.EdgeEffectCompat} classes. </p>
55
56<p>A scroller is used to animate scrolling over time, using platform-standard
57scrolling physics (friction, velocity, etc.). The scroller itself doesn't
58actually draw anything. Scrollers track scroll offsets for you over time, but
59they don't automatically apply those positions to your view. It's your
60responsibility to get and apply new coordinates at a rate that will make the
61scrolling animation look smooth.</p>
62
63<p class="note"><strong>Note:</strong> You generally only need to use scrollers
64when implementing scrolling yourself. {@link android.widget.ScrollView} and
65{@link android.widget.HorizontalScrollView} do all this for you do all of this for you if you nest your layout within them.</p>
66
67<h2 id = "scroll">Implement Touch-Based Scrolling</h2>
68
69
70<p>This snippet illustrates the basics of using a scroller. It uses a
71{@link android.view.GestureDetector}, and overrides the
72{@link android.view.GestureDetector.SimpleOnGestureListener} methods
73{@link android.view.GestureDetector.OnGestureListener#onDown onDown()} and
74{@link android.view.GestureDetector.OnGestureListener#onFling onFling()}. It also
75overrides {@link android.view.GestureDetector.OnGestureListener#onScroll onScroll()}
76to return {@code false} since you don't need to animate a scroll.</p>
77
78
79<p>It's common to use scrollers in conjunction with a fling gesture, but they
80can be used in pretty much any context where you want the UI to display
81scrolling in response to a touch event. For example, you could override {@link
82android.view.View#onTouchEvent onTouchEvent()} to process touch events directly,
83and produce a scrolling effect in response to those touch events.</p>
84
85<pre>
86private OverScroller mScroller = new OverScroller(context);
87
88private GestureDetector.SimpleOnGestureListener mGestureListener
89 = new GestureDetector.SimpleOnGestureListener() {
90 &#64;Override
91 public boolean onDown(MotionEvent e) {
92 // Abort any active scroll animations and invalidate.
93 mScroller.forceFinished(true);
94 // There is also a compatibility version:
95 // ViewCompat.postInvalidateOnAnimation
96 postInvalidateOnAnimation();
97 return true;
98 }
99
100 &#64;Override
101 public boolean onScroll(MotionEvent e1, MotionEvent e2,
102 float distanceX, float distanceY) {
103 // You don't use a scroller in onScroll because you don't need to animate
104 // a scroll. The scroll occurs instantly in response to touch feedback.
105 return false;
106 }
107
108 &#64;Override
109 public boolean onFling(MotionEvent e1, MotionEvent e2,
110 float velocityX, float velocityY) {
111 // Before flinging, abort the current animation.
112 mScroller.forceFinished(true);
113 // Begin the scroll animation
114 mScroller.fling(
115 // Current scroll position
116 startX,
117 startY,
118 // Velocities, negated for natural touch response
119 (int) -velocityX,
120 (int) -velocityY,
121 // Minimum and maximum scroll positions. The minimum scroll
122 // position is generally zero and the maximum scroll position
123 // is generally the content size less the screen size. So if the
124 // content width is 1000 pixels and the screen width is 200
125 // pixels, the maximum scroll offset should be 800 pixels.
126 minX, maxX,
127 minY, maxY,
128 // The maximum overscroll bounds. This is useful when using
129 // the EdgeEffect class to draw overscroll "glow" overlays.
130 mContentRect.width() / 2,
131 mContentRect.height() / 2);
132 // Invalidate to trigger computeScroll()
133 postInvalidateOnAnimation();
134 return true;
135 }
136};
137
138&#64;Override
139public void computeScroll() {
140 super.computeScroll();
141
142 // Compute the current scroll offsets. If this returns true, then the
143 // scroll has not yet finished.
144 if (mScroller.computeScrollOffset()) {
145 int currX = mScroller.getCurrX();
146 int currY = mScroller.getCurrY();
147
148 // Actually render the scrolled viewport, or actually scroll the
149 // view using View.scrollTo.
150
151 // If currX or currY are outside the bounds, render the overscroll
152 // glow using EdgeEffect.
153
154 } else {
155 // The scroll has finished.
156 }
157}</pre>
158
159<p>For another example of scroller usage, see the <a href="http://github.com/android/platform_frameworks_support/blob/master/v4/java/android/support/v4/view/ViewPager.java">source code</a> for the
160{@link android.support.v4.view.ViewPager} class. It scrolls in response to flings,
161and uses scrolling to implement the "snapping to page" animation.</p>