Android Scroller类介绍

资料:http://blog.csdn.net/gemmem/article/details/7321910

Scroller源码:

  1 /*
  2  * Copyright (C) 2006 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 android.widget;
 18
 19 import android.content.Context;
 20 import android.hardware.SensorManager;
 21 import android.os.Build;
 22 import android.util.FloatMath;
 23 import android.view.ViewConfiguration;
 24 import android.view.animation.AnimationUtils;
 25 import android.view.animation.Interpolator;
 26
 27
 28 /**
 29  * This class encapsulates scrolling.  The duration of the scroll
 30  * can be passed in the constructor and specifies the maximum time that
 31  * the scrolling animation should take.  Past this time, the scrolling is
 32  * automatically moved to its final stage and computeScrollOffset()
 33  * will always return false to indicate that scrolling is over.
 34  */
 35 public class Scroller  {
 36     private int mMode;
 37
 38     private int mStartX;
 39     private int mStartY;
 40     private int mFinalX;
 41     private int mFinalY;
 42
 43     private int mMinX;
 44     private int mMaxX;
 45     private int mMinY;
 46     private int mMaxY;
 47
 48     private int mCurrX;
 49     private int mCurrY;
 50     private long mStartTime;
 51     private int mDuration;
 52     private float mDurationReciprocal;
 53     private float mDeltaX;
 54     private float mDeltaY;
 55     private boolean mFinished;
 56     private Interpolator mInterpolator;
 57     private boolean mFlywheel;
 58
 59     private float mVelocity;
 60
 61     private static final int DEFAULT_DURATION = 250;
 62     private static final int SCROLL_MODE = 0;
 63     private static final int FLING_MODE = 1;
 64
 65     private static float DECELERATION_RATE = (float) (Math.log(0.75) / Math.log(0.9));
 66     private static float ALPHA = 800; // pixels / seconds
 67     private static float START_TENSION = 0.4f; // Tension at start: (0.4 * total T, 1.0 * Distance)
 68     private static float END_TENSION = 1.0f - START_TENSION;
 69     private static final int NB_SAMPLES = 100;
 70     private static final float[] SPLINE = new float[NB_SAMPLES + 1];
 71
 72     private float mDeceleration;
 73     private final float mPpi;
 74
 75     static {
 76         float x_min = 0.0f;
 77         for (int i = 0; i <= NB_SAMPLES; i++) {
 78             final float t = (float) i / NB_SAMPLES;
 79             float x_max = 1.0f;
 80             float x, tx, coef;
 81             while (true) {
 82                 x = x_min + (x_max - x_min) / 2.0f;
 83                 coef = 3.0f * x * (1.0f - x);
 84                 tx = coef * ((1.0f - x) * START_TENSION + x * END_TENSION) + x * x * x;
 85                 if (Math.abs(tx - t) < 1E-5) break;
 86                 if (tx > t) x_max = x;
 87                 else x_min = x;
 88             }
 89             final float d = coef + x * x * x;
 90             SPLINE[i] = d;
 91         }
 92         SPLINE[NB_SAMPLES] = 1.0f;
 93
 94         // This controls the viscous fluid effect (how much of it)
 95         sViscousFluidScale = 8.0f;
 96         // must be set to 1.0 (used in viscousFluid())
 97         sViscousFluidNormalize = 1.0f;
 98         sViscousFluidNormalize = 1.0f / viscousFluid(1.0f);
 99     }
100
101     private static float sViscousFluidScale;
102     private static float sViscousFluidNormalize;
103
104     /**
105      * Create a Scroller with the default duration and interpolator.
106      */
107     public Scroller(Context context) {
108         this(context, null);
109     }
110
111     /**
112      * Create a Scroller with the specified interpolator. If the interpolator is
113      * null, the default (viscous) interpolator will be used. "Flywheel" behavior will
114      * be in effect for apps targeting Honeycomb or newer.
115      */
116     public Scroller(Context context, Interpolator interpolator) {
117         this(context, interpolator,
118                 context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB);
119     }
120
121     /**
122      * Create a Scroller with the specified interpolator. If the interpolator is
123      * null, the default (viscous) interpolator will be used. Specify whether or
124      * not to support progressive "flywheel" behavior in flinging.
125      */
126     public Scroller(Context context, Interpolator interpolator, boolean flywheel) {
127         mFinished = true;
128         mInterpolator = interpolator;
129         mPpi = context.getResources().getDisplayMetrics().density * 160.0f;
130         mDeceleration = computeDeceleration(ViewConfiguration.getScrollFriction());
131         mFlywheel = flywheel;
132     }
133
134     /**
135      * The amount of friction applied to flings. The default value
136      * is {@link ViewConfiguration#getScrollFriction}.
137      *
138      * @param friction A scalar dimension-less value representing the coefficient of
139      *         friction.
140      */
141     public final void setFriction(float friction) {
142         mDeceleration = computeDeceleration(friction);
143     }
144
145     private float computeDeceleration(float friction) {
146         return SensorManager.GRAVITY_EARTH   // g (m/s^2)
147                       * 39.37f               // inch/meter
148                       * mPpi                 // pixels per inch
149                       * friction;
150     }
151
152     /**
153      *
154      * Returns whether the scroller has finished scrolling.
155      *
156      * @return True if the scroller has finished scrolling, false otherwise.
157      */
158     public final boolean isFinished() {
159         return mFinished;
160     }
161
162     /**
163      * Force the finished field to a particular value.
164      *
165      * @param finished The new finished value.
166      */
167     public final void forceFinished(boolean finished) {
168         mFinished = finished;
169     }
170
171     /**
172      * Returns how long the scroll event will take, in milliseconds.
173      *
174      * @return The duration of the scroll in milliseconds.
175      */
176     public final int getDuration() {
177         return mDuration;
178     }
179
180     /**
181      * Returns the current X offset in the scroll.
182      *
183      * @return The new X offset as an absolute distance from the origin.
184      */
185     public final int getCurrX() {
186         return mCurrX;
187     }
188
189     /**
190      * Returns the current Y offset in the scroll.
191      *
192      * @return The new Y offset as an absolute distance from the origin.
193      */
194     public final int getCurrY() {
195         return mCurrY;
196     }
197
198     /**
199      * Returns the current velocity.
200      *
201      * @return The original velocity less the deceleration. Result may be
202      * negative.
203      */
204     public float getCurrVelocity() {
205         return mVelocity - mDeceleration * timePassed() / 2000.0f;
206     }
207
208     /**
209      * Returns the start X offset in the scroll.
210      *
211      * @return The start X offset as an absolute distance from the origin.
212      */
213     public final int getStartX() {
214         return mStartX;
215     }
216
217     /**
218      * Returns the start Y offset in the scroll.
219      *
220      * @return The start Y offset as an absolute distance from the origin.
221      */
222     public final int getStartY() {
223         return mStartY;
224     }
225
226     /**
227      * Returns where the scroll will end. Valid only for "fling" scrolls.
228      *
229      * @return The final X offset as an absolute distance from the origin.
230      */
231     public final int getFinalX() {
232         return mFinalX;
233     }
234
235     /**
236      * Returns where the scroll will end. Valid only for "fling" scrolls.
237      *
238      * @return The final Y offset as an absolute distance from the origin.
239      */
240     public final int getFinalY() {
241         return mFinalY;
242     }
243
244     /**
245      * Call this when you want to know the new location.  If it returns true,
246      * the animation is not yet finished.  loc will be altered to provide the
247      * new location.
248      */
249     public boolean computeScrollOffset() {
250         if (mFinished) {
251             return false;
252         }
253
254         int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);
255
256         if (timePassed < mDuration) {
257             switch (mMode) {
258             case SCROLL_MODE:
259                 float x = timePassed * mDurationReciprocal;
260
261                 if (mInterpolator == null)
262                     x = viscousFluid(x);
263                 else
264                     x = mInterpolator.getInterpolation(x);
265
266                 mCurrX = mStartX + Math.round(x * mDeltaX);
267                 mCurrY = mStartY + Math.round(x * mDeltaY);
268                 break;
269             case FLING_MODE:
270                 final float t = (float) timePassed / mDuration;
271                 final int index = (int) (NB_SAMPLES * t);
272                 final float t_inf = (float) index / NB_SAMPLES;
273                 final float t_sup = (float) (index + 1) / NB_SAMPLES;
274                 final float d_inf = SPLINE[index];
275                 final float d_sup = SPLINE[index + 1];
276                 final float distanceCoef = d_inf + (t - t_inf) / (t_sup - t_inf) * (d_sup - d_inf);
277
278                 mCurrX = mStartX + Math.round(distanceCoef * (mFinalX - mStartX));
279                 // Pin to mMinX <= mCurrX <= mMaxX
280                 mCurrX = Math.min(mCurrX, mMaxX);
281                 mCurrX = Math.max(mCurrX, mMinX);
282
283                 mCurrY = mStartY + Math.round(distanceCoef * (mFinalY - mStartY));
284                 // Pin to mMinY <= mCurrY <= mMaxY
285                 mCurrY = Math.min(mCurrY, mMaxY);
286                 mCurrY = Math.max(mCurrY, mMinY);
287
288                 if (mCurrX == mFinalX && mCurrY == mFinalY) {
289                     mFinished = true;
290                 }
291
292                 break;
293             }
294         }
295         else {
296             mCurrX = mFinalX;
297             mCurrY = mFinalY;
298             mFinished = true;
299         }
300         return true;
301     }
302
303     /**
304      * Start scrolling by providing a starting point and the distance to travel.
305      * The scroll will use the default value of 250 milliseconds for the
306      * duration.
307      *
308      * @param startX Starting horizontal scroll offset in pixels. Positive
309      *        numbers will scroll the content to the left.
310      * @param startY Starting vertical scroll offset in pixels. Positive numbers
311      *        will scroll the content up.
312      * @param dx Horizontal distance to travel. Positive numbers will scroll the
313      *        content to the left.
314      * @param dy Vertical distance to travel. Positive numbers will scroll the
315      *        content up.
316      */
317     public void startScroll(int startX, int startY, int dx, int dy) {
318         startScroll(startX, startY, dx, dy, DEFAULT_DURATION);
319     }
320
321     /**
322      * Start scrolling by providing a starting point and the distance to travel.
323      *
324      * @param startX Starting horizontal scroll offset in pixels. Positive
325      *        numbers will scroll the content to the left.
326      * @param startY Starting vertical scroll offset in pixels. Positive numbers
327      *        will scroll the content up.
328      * @param dx Horizontal distance to travel. Positive numbers will scroll the
329      *        content to the left.
330      * @param dy Vertical distance to travel. Positive numbers will scroll the
331      *        content up.
332      * @param duration Duration of the scroll in milliseconds.
333      */
334     public void startScroll(int startX, int startY, int dx, int dy, int duration) {
335         mMode = SCROLL_MODE;
336         mFinished = false;
337         mDuration = duration;
338         mStartTime = AnimationUtils.currentAnimationTimeMillis();
339         mStartX = startX;
340         mStartY = startY;
341         mFinalX = startX + dx;
342         mFinalY = startY + dy;
343         mDeltaX = dx;
344         mDeltaY = dy;
345         mDurationReciprocal = 1.0f / (float) mDuration;
346     }
347
348     /**
349      * Start scrolling based on a fling gesture. The distance travelled will
350      * depend on the initial velocity of the fling.
351      *
352      * @param startX Starting point of the scroll (X)
353      * @param startY Starting point of the scroll (Y)
354      * @param velocityX Initial velocity of the fling (X) measured in pixels per
355      *        second.
356      * @param velocityY Initial velocity of the fling (Y) measured in pixels per
357      *        second
358      * @param minX Minimum X value. The scroller will not scroll past this
359      *        point.
360      * @param maxX Maximum X value. The scroller will not scroll past this
361      *        point.
362      * @param minY Minimum Y value. The scroller will not scroll past this
363      *        point.
364      * @param maxY Maximum Y value. The scroller will not scroll past this
365      *        point.
366      */
367     public void fling(int startX, int startY, int velocityX, int velocityY,
368             int minX, int maxX, int minY, int maxY) {
369         // Continue a scroll or fling in progress
370         if (mFlywheel && !mFinished) {
371             float oldVel = getCurrVelocity();
372
373             float dx = (float) (mFinalX - mStartX);
374             float dy = (float) (mFinalY - mStartY);
375             float hyp = FloatMath.sqrt(dx * dx + dy * dy);
376
377             float ndx = dx / hyp;
378             float ndy = dy / hyp;
379
380             float oldVelocityX = ndx * oldVel;
381             float oldVelocityY = ndy * oldVel;
382             if (Math.signum(velocityX) == Math.signum(oldVelocityX) &&
383                     Math.signum(velocityY) == Math.signum(oldVelocityY)) {
384                 velocityX += oldVelocityX;
385                 velocityY += oldVelocityY;
386             }
387         }
388
389         mMode = FLING_MODE;
390         mFinished = false;
391
392         float velocity = FloatMath.sqrt(velocityX * velocityX + velocityY * velocityY);
393
394         mVelocity = velocity;
395         final double l = Math.log(START_TENSION * velocity / ALPHA);
396         mDuration = (int) (1000.0 * Math.exp(l / (DECELERATION_RATE - 1.0)));
397         mStartTime = AnimationUtils.currentAnimationTimeMillis();
398         mStartX = startX;
399         mStartY = startY;
400
401         float coeffX = velocity == 0 ? 1.0f : velocityX / velocity;
402         float coeffY = velocity == 0 ? 1.0f : velocityY / velocity;
403
404         int totalDistance =
405                 (int) (ALPHA * Math.exp(DECELERATION_RATE / (DECELERATION_RATE - 1.0) * l));
406
407         mMinX = minX;
408         mMaxX = maxX;
409         mMinY = minY;
410         mMaxY = maxY;
411
412         mFinalX = startX + Math.round(totalDistance * coeffX);
413         // Pin to mMinX <= mFinalX <= mMaxX
414         mFinalX = Math.min(mFinalX, mMaxX);
415         mFinalX = Math.max(mFinalX, mMinX);
416
417         mFinalY = startY + Math.round(totalDistance * coeffY);
418         // Pin to mMinY <= mFinalY <= mMaxY
419         mFinalY = Math.min(mFinalY, mMaxY);
420         mFinalY = Math.max(mFinalY, mMinY);
421     }
422
423     static float viscousFluid(float x)
424     {
425         x *= sViscousFluidScale;
426         if (x < 1.0f) {
427             x -= (1.0f - (float)Math.exp(-x));
428         } else {
429             float start = 0.36787944117f;   // 1/e == exp(-1)
430             x = 1.0f - (float)Math.exp(1.0f - x);
431             x = start + x * (1.0f - start);
432         }
433         x *= sViscousFluidNormalize;
434         return x;
435     }
436
437     /**
438      * Stops the animation. Contrary to {@link #forceFinished(boolean)},
439      * aborting the animating cause the scroller to move to the final x and y
440      * position
441      *
442      * @see #forceFinished(boolean)
443      */
444     public void abortAnimation() {
445         mCurrX = mFinalX;
446         mCurrY = mFinalY;
447         mFinished = true;
448     }
449
450     /**
451      * Extend the scroll animation. This allows a running animation to scroll
452      * further and longer, when used with {@link #setFinalX(int)} or {@link #setFinalY(int)}.
453      *
454      * @param extend Additional time to scroll in milliseconds.
455      * @see #setFinalX(int)
456      * @see #setFinalY(int)
457      */
458     public void extendDuration(int extend) {
459         int passed = timePassed();
460         mDuration = passed + extend;
461         mDurationReciprocal = 1.0f / mDuration;
462         mFinished = false;
463     }
464
465     /**
466      * Returns the time elapsed since the beginning of the scrolling.
467      *
468      * @return The elapsed time in milliseconds.
469      */
470     public int timePassed() {
471         return (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);
472     }
473
474     /**
475      * Sets the final position (X) for this scroller.
476      *
477      * @param newX The new X offset as an absolute distance from the origin.
478      * @see #extendDuration(int)
479      * @see #setFinalY(int)
480      */
481     public void setFinalX(int newX) {
482         mFinalX = newX;
483         mDeltaX = mFinalX - mStartX;
484         mFinished = false;
485     }
486
487     /**
488      * Sets the final position (Y) for this scroller.
489      *
490      * @param newY The new Y offset as an absolute distance from the origin.
491      * @see #extendDuration(int)
492      * @see #setFinalX(int)
493      */
494     public void setFinalY(int newY) {
495         mFinalY = newY;
496         mDeltaY = mFinalY - mStartY;
497         mFinished = false;
498     }
499
500     /**
501      * @hide
502      */
503     public boolean isScrollingInDirection(float xvel, float yvel) {
504         return !mFinished && Math.signum(xvel) == Math.signum(mFinalX - mStartX) &&
505                 Math.signum(yvel) == Math.signum(mFinalY - mStartY);
506     }
507 }

Scroller源码只有507行,结合链接中资料发现,Scroller只是一个计算滚动位置的帮助类,用来计算出当前应该滚动到的位置,而且每次获取位置必须调用computeScrollOffset方法才能刷新,Scroller还是很好用的,按照这个思路,以后如果滑动需要特殊计算可以按照Scroller自定义一个计算类。

时间: 2024-11-23 18:41:05

Android Scroller类介绍的相关文章

Android Paint类介绍以及浮雕和阴影效果的设置

Paint类介绍 Paint即画笔,在绘制文本和图形用它来设置图形颜色, 样式等绘制信息. 1.图形绘制 setARGB(int a,int r,int g,int b); 设置绘制的颜色,a代表透明度,r,g,b代表颜色值. setAlpha(int a); 设置绘制图形的透明度. setColor(int color); 设置绘制的颜色,使用颜色值来表示,该颜色值包括透明度和RGB颜色. setAntiAlias(boolean aa); 设置是否使用抗锯齿功能,会消耗较大资源,绘制图形速度

Android Scroller类和VelocityTracker类

Scroller类 Scroller类封装了滚动,用于计算view滚动的位置,可以设置滚动发生的时长,滚动结束时computeScrollOffset函数会返回false,否则返回true. 常用函数: public void startScroll(int startX,int startY,int dx,int dy,int duration):设置滚动的起点坐标,横轴和纵轴滚动的距离以及滚动的时间.要注意的是dx<0是往右滚动,dy<0是往下滚动 public boolean compu

Android - Paint类介绍

Paint即画笔,在绘图过程中起到了极其重要的作用,画笔主要保存了颜色, * 样式等绘制信息,指定了如何绘制文本和图形,画笔对象有很多设置方法, * 大体上可以分为两类,一类与图形绘制相关,一类与文本绘制相关. 1.图形绘制 setARGB(int a,int r,int g,int b); 设置绘制的颜色,a代表透明度,r,g,b代表颜色值. setAlpha(int a); 设置绘制图形的透明度. setColor(int color); 设置绘制的颜色,使用颜色值来表示,该颜色值包括透明度

Android自己定义组件系列【2】——Scroller类

在上一篇中介绍了View类的scrollTo和scrollBy两个方法,对这两个方法不太了解的朋友能够先看<自己定义View及ViewGroup> scrollTo和scrollBy尽管实现了视图的偏移,可是却没有更好的控制移动过程,移动是瞬间进行的.Scroller类就是为解决问题而设计的. 打开Scroller的源码,能够看到startScroll方法: /** * Start scrolling by providing a starting point and the distance

Android学习之 Scroller的介绍与使用

类概述 Android里Scroller类是为了实现View平滑滚动的一个Helper类.通常在自定义的View时使用,在View中定义一个私有成员mScroller = new Scroller(context).设置mScroller滚动的位置时,并不会导致View的滚动,通常是用mScroller*记录/计算View滚动的位置*,再重写View的computeScroll(),调用View的scrollTo(int x,int y)方法完成实际的滚动. 主要方法介绍 更多关于Scrolle

Android 界面滑动实现---Scroller类 从源码和开发文档中学习(让你的布局动起来)

在android学习中,动作交互是软件中重要的一部分,其中的Scroller就是提供了拖动效果的类,在网上,比如说一些Launcher实现滑屏都可以通过这个类去实现.. 在广泛使用的侧边滑动导航开源库 --SlidingLayer其实就是使用到了Scroller类进行的实现,下载地址:GITHUB  ,下面要讲的不是这个库,而是这个库的实现过程中使用到的---Scroller类,懂了之后你看库的源码就知道,原来它是这样实现的. Scroller类使用过程中,懂得以下机制可能会对开发更有帮助: 1

Android 界面滑动实现---Scroller类 从源码和开发文档中学习(让你的布局动起来)

在android学习中,动作交互是软件中重要的一部分,其中的Scroller就是提供了拖动效果的类,在网上,比如说一些Launcher实现滑屏都可以通过这个类去实现.. 例子相关博文:Android 仿 窗帘效果 和 登录界面拖动效果 (Scroller类的应用) 附 2个DEMO及源码 在广泛使用的侧边滑动导航开源库 --SlidingLayer其实就是使用到了Scroller类进行的实现,下载地址:GITHUB  ,下面要讲的不是这个库,而是这个库的实现过程中使用到的---Scroller类

Android中滑屏实现----触摸滑屏以及Scroller类详解 .

转:http://blog.csdn.net/qinjuning/article/details/7419207 知识点一:  关于scrollTo()和scrollBy()以及偏移坐标的设置/取值问题 scrollTo()和scrollBy()这两个方法的主要作用是将View/ViewGroup移至指定的坐标中,并且将偏移量保存起来.另外: mScrollX 代表X轴方向的偏移坐标 mScrollY 代表Y轴方向的偏移坐标 关于偏移量的设置我们可以参看下源码: package com.qin.

[Android自定义控件] Android Scroller工具类和GestureDetector的简单用法

转载:http://ipjmc.iteye.com/blog/1615828 Android里Scroller类是为了实现View平滑滚动的一个Helper类.通常在自定义的View时使用,在View中定义一个私有成员mScroller = new Scroller(context).设置mScroller滚动的位置时,并不会导致View的滚动,通常是用mScroller记录/计算View滚动的位置,再重写View的computeScroll(),完成实际的滚动. mScroller.getCu