Android里Scroller类是为了实现View平滑滚动的一个Helper类。通常在自定义的View时使用,在View中定义一个私有成员mScroller = new Scroller(context)。设置mScroller滚动的位置时,并不会导致View的滚动,通常是用mScroller记录/计算View滚动的位置,再重写View的computeScroll(),完成实际的滚动。
相关API介绍如下
<embed src="http://ipjmc.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" type="application/x-shockwave-flash" width="14" height="15">
</embed>
<a title="收藏这段代码"></a>
</div>
- mScroller.getCurrX() <span class="comment">//获取mScroller当前水平滚动的位置</span>
- mScroller.getCurrY() <span class="comment">//获取mScroller当前竖直滚动的位置</span>
- mScroller.getFinalX() <span class="comment">//获取mScroller最终停止的水平位置</span>
- mScroller.getFinalY() <span class="comment">//获取mScroller最终停止的竖直位置</span>
- mScroller.setFinalX(<span class="keyword">int</span> newX) <span class="comment">//设置mScroller最终停留的水平位置,没有动画效果,直接跳到目标位置</span>
- mScroller.setFinalY(<span class="keyword">int</span> newY) <span class="comment">//设置mScroller最终停留的竖直位置,没有动画效果,直接跳到目标位置</span>
-
- <span class="comment">//滚动,startX, startY为开始滚动的位置,dx,dy为滚动的偏移量, duration为完成滚动的时间</span>
- mScroller.startScroll(<span class="keyword">int</span> startX, <span class="keyword">int</span> startY, <span class="keyword">int</span> dx, <span class="keyword">int</span> dy) <span class="comment">//使用默认完成时间250ms</span>
- mScroller.startScroll(<span class="keyword">int</span> startX, <span class="keyword">int</span> startY, <span class="keyword">int</span> dx, <span class="keyword">int</span> dy, <span class="keyword">int</span> duration)
-
- mScroller.computeScrollOffset() <span class="comment">//返回值为boolean,true说明滚动尚未完成,false说明滚动已经完成。这是一个很重要的方法,通常放在View.computeScroll()中,用来判断是否滚动是否结束。</span>
举例说明,自定义一个CustomView,使用Scroller实现滚动:
<embed src="http://ipjmc.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" type="application/x-shockwave-flash" width="14" height="15">
</embed>
<a title="收藏这段代码"></a>
</div>
- <span class="keyword">import</span> android.content.Context;
- <span class="keyword">import</span> android.util.AttributeSet;
- <span class="keyword">import</span> android.util.Log;
- <span class="keyword">import</span> android.view.View;
- <span class="keyword">import</span> android.widget.LinearLayout;
- <span class="keyword">import</span> android.widget.Scroller;
-
- <span class="keyword">public</span> <span class="keyword">class</span> CustomView <span class="keyword">extends</span> LinearLayout {
-
- <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> String TAG = <span class="string">“Scroller”</span>;
-
- <span class="keyword">private</span> Scroller mScroller;
-
- <span class="keyword">public</span> CustomView(Context context, AttributeSet attrs) {
- <span class="keyword">super</span>(context, attrs);
- mScroller = <span class="keyword">new</span> Scroller(context);
- }
-
- <span class="comment">//调用此方法滚动到目标位置</span>
- <span class="keyword">public</span> <span class="keyword">void</span> smoothScrollTo(<span class="keyword">int</span> fx, <span class="keyword">int</span> fy) {
- <span class="keyword">int</span> dx = fx – mScroller.getFinalX();
- <span class="keyword">int</span> dy = fy – mScroller.getFinalY();
- smoothScrollBy(dx, dy);
- }
-
- <span class="comment">//调用此方法设置滚动的相对偏移</span>
- <span class="keyword">public</span> <span class="keyword">void</span> smoothScrollBy(<span class="keyword">int</span> dx, <span class="keyword">int</span> dy) {
-
- <span class="comment">//设置mScroller的滚动偏移量</span>
- mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), dx, dy);
- invalidate();<span class="comment">//这里必须调用invalidate()才能保证computeScroll()会被调用,否则不一定会刷新界面,看不到滚动效果</span>
- }
-
- <span class="annotation">@Override</span>
- <span class="keyword">public</span> <span class="keyword">void</span> computeScroll() {
-
- <span class="comment">//先判断mScroller滚动是否完成</span>
- <span class="keyword">if</span> (mScroller.computeScrollOffset()) {
-
- <span class="comment">//这里调用View的scrollTo()完成实际的滚动</span>
- scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
-
- <span class="comment">//必须调用该方法,否则不一定能看到滚动效果</span>
- postInvalidate();
- }
- <span class="keyword">super</span>.computeScroll();
- }
- }
- 转自:http://ipjmc.iteye.com/blog/1615828
public class CustomView extends LinearLayout {
private static final String TAG = CustomView.class.getName();
// 定义一个滑动 private Scroller mScroller; //手势 private GestureDetector mGestureDetector;
public CustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle); mScroller = new Scroller(context); mGestureDetector = new GestureDetector(context, new CustomGestureListener()); }
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs); mScroller = new Scroller(context); mGestureDetector = new GestureDetector(context, new CustomGestureListener()); }
public CustomView(Context context) {
super(context); mScroller = new Scroller(context); mGestureDetector = new GestureDetector(context, new CustomGestureListener()); // setClickable(true); // setLongClickable(true); }
// 调用此方法滚动到目标位置
public void smoothScrollTo(int fx, int fy) { int dx = fx – mScroller.getFinalX(); int dy = fy – mScroller.getFinalY(); smoothScrollBy(dx, dy); }
// 调用此方法设置滚动的相对偏移
public void smoothScrollBy(int dx, int dy) { // 设置mScroller的滚动偏移量 mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), dx, dy); invalidate();// 这里必须调用invalidate()才能保证computeScroll()会被调用,否则不一定会刷新界面,看不到滚动效果 }
/**
完成实际的滚动 */ @Override public void computeScroll() { // 判断Scroll是否滚动完成 if (mScroller.computeScrollOffset()) { // 调用View 的scrollto完成实际的滚动 scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); //必须调用该方法,否则不一定能看到滚动效果 postInvalidate(); } super.computeScroll(); }
@Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_UP : Log.e(TAG, “get Sy” + getScrollY()); smoothScrollTo(0, 0); break; default: return mGestureDetector.onTouchEvent(event); } return super.onTouchEvent(event); }
class CustomGestureListener implements GestureDetector.OnGestureListener {
@Override public boolean onDown(MotionEvent e) { // TODO Auto-generated method stub return true; }
@Override public void onShowPress(MotionEvent e) { // TODO Auto-generated method stub
}
@Override public boolean onSingleTapUp(MotionEvent e) { // TODO Auto-generated method stub return false; }
@Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
int dis = (int)((distanceY-0.5)/2); Log.e(TAG, dis + “.”); smoothScrollBy(0, dis); return false; }
@Override public void onLongPress(MotionEvent e) { // TODO Auto-generated method stub
}
@Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // TODO Auto-generated method stub return false; }
} }
转载请声明:http://bbs.niuzhi.cc/thread-24-1-1.html
在Launcher中的Workspace中实现了左右屏幕切换效果,里面就用到了Scroller记录滑动轨迹,实现一种缓慢地向左或向右移动的效果,这里我对这种效果进行总结:
我们先看一个例子:点击按钮时红经块会从左边缓慢地移向左右,这个该怎么实现呢

我们先来看一下,Scroller,这个对象里有startScroll方法
void android.widget.Scroller.startScroll(int startX, int startY, int dx, int dy, int duration) 第一个参数是起始移动的x坐标值,第二个是起始移动的y坐标值,第三个第四个参数都是移到某点的坐标值,而**duration **当然就是执行移动的时间。这个有什么用呢。要知道有什么用还得再看一个方法
当startScroll执行过程中即在duration时间内,**computeScrollOffset **方法会一直返回false,但当动画执行完成后会返回返加true.
有了这两个方法还不够,我们还需要再重写viewGroup的一个方法,
**computeScroll 这个方法什么时候会被调用呢**
**官网上这样说的**
public void computeScroll ()#
Called by a parent to request that a child update its values for mScrollX and mScrollY if necessary. This will typically be done if the child is animating a scroll using a `<a href="http://developer.android.com/reference/android/widget/Scroller.html">Scroller</a>` object.
</div>
当我们执行ontouch或invalidate()或postInvalidate()都会导致这个方法的执行
**所以我们像下面这样调用,**postInvalidate执行后,会去调**computeScroll 方法,而这个方法里再去调<strong>postInvalidate,这样******就可以不断地去调用scrollTo方法了,直到mScroller动画结束,当然第一次时,我们需要手动去调用一次**postInvalidate才会去调用 **</strong>
computeScroll 方法#
<div>
<embed id="ZeroClipboardMovie_1" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_1">
</embed>
</div>
</div>
</div>
- <span class="annotation">@Override</span>
- <span class="keyword">public</span> <span class="keyword">void</span> computeScroll() {
- <span class="keyword">if</span> (mScroller.computeScrollOffset()) {
- scrollTo(mScroller.getCurrX(), <span class="number"></span>);
- postInvalidate();
- }
- }
下面附上上面那个例子的源代码
首先是MyViewGroup.java
<div>
<embed id="ZeroClipboardMovie_2" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_2">
</embed>
</div>
</div>
</div>
- <span class="keyword">package</span> com.wb;
-
- <span class="keyword">import</span> android.content.Context;
- <span class="keyword">import</span> android.util.AttributeSet;
- <span class="keyword">import</span> android.view.View;
- <span class="keyword">import</span> android.view.ViewGroup;
- <span class="keyword">import</span> android.widget.LinearLayout;
- <span class="keyword">import</span> android.widget.Scroller;
-
- <span class="keyword">public</span> <span class="keyword">class</span> MyViewGroup <span class="keyword">extends</span> LinearLayout {
- <span class="keyword">private</span> <span class="keyword">boolean</span> s1=<span class="keyword">true</span>;
- Scroller mScroller=<span class="keyword">null</span>;
- <span class="keyword">public</span> MyViewGroup(Context context, AttributeSet attrs) {
- <span class="keyword">super</span>(context, attrs);
- mScroller=<span class="keyword">new</span> Scroller(context);
- <span class="comment">// TODO Auto-generated constructor stub</span>
- }
- <span class="annotation">@Override</span>
- <span class="keyword">public</span> <span class="keyword">void</span> computeScroll() {
- <span class="keyword">if</span> (mScroller.computeScrollOffset()) {
- scrollTo(mScroller.getCurrX(), <span class="number"></span>);
- postInvalidate();
- }
- }
- <span class="keyword">public</span> <span class="keyword">void</span> beginScroll(){
- <span class="keyword">if</span> (!s1) {
- mScroller.startScroll(<span class="number"></span>, <span class="number"></span>, <span class="number"></span>, <span class="number"></span>, <span class="number">1000</span>);
- s1 = <span class="keyword">true</span>;
- } <span class="keyword">else</span> {
- mScroller.startScroll(<span class="number"></span>, <span class="number"></span>, –<span class="number">500</span>, <span class="number"></span>, <span class="number">1000</span>);
- s1 = <span class="keyword">false</span>;
- }
- invalidate();
- }
- }
然后是WheelActivity.java
<div>
<embed id="ZeroClipboardMovie_3" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_3">
</embed>
</div>
</div>
</div>
- <span class="keyword">package</span> com.wb;
-
- <span class="keyword">import</span> android.app.Activity;
- <span class="keyword">import</span> android.graphics.Color;
- <span class="keyword">import</span> android.os.Bundle;
- <span class="keyword">import</span> android.view.Gravity;
- <span class="keyword">import</span> android.view.View;
- <span class="keyword">import</span> android.view.ViewGroup;
- <span class="keyword">import</span> android.widget.AbsListView;
- <span class="keyword">import</span> android.widget.AbsListView.LayoutParams;
- <span class="keyword">import</span> android.widget.AbsListView.OnScrollListener;
- <span class="keyword">import</span> android.widget.Adapter;
- <span class="keyword">import</span> android.widget.BaseAdapter;
- <span class="keyword">import</span> android.widget.ListView;
- <span class="keyword">import</span> android.widget.TextView;
-
- <span class="keyword">public</span> <span class="keyword">class</span> WheelActivity <span class="keyword">extends</span> Activity {
-
- <span class="keyword">private</span> ListView listView = <span class="keyword">null</span>;
- <span class="keyword">private</span> MyViewGroup myViewGroup;
-
- <span class="annotation">@Override</span>
- <span class="keyword">public</span> <span class="keyword">void</span> onCreate(Bundle savedInstanceState) {
- <span class="keyword">super</span>.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- myViewGroup = (MyViewGroup) findViewById(R.id.myviewGroup);
-
- }
-
- <span class="keyword">public</span> <span class="keyword">void</span> scroll(View view) {
-
- myViewGroup.beginScroll();
-
- }
-
- }
main.xml
<div>
<embed id="ZeroClipboardMovie_4" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_4">
</embed>
</div>
</div>
</div>
- <span class="tag"><?</span><span class="tag-name">xml</span> <span class="attribute">version</span>=<span class="attribute-value">“1.0”</span> <span class="attribute">encoding</span>=<span class="attribute-value">“utf-8”</span><span class="tag">?></span>
- <span class="tag"><</span><span class="tag-name">LinearLayout</span> <span class="attribute">xmlns:android</span>=<span class="attribute-value">“http://schemas.android.com/apk/res/android”</span>
- <span class="attribute">android:layout_width</span>=<span class="attribute-value">“fill_parent”</span>
- <span class="attribute">android:layout_height</span>=<span class="attribute-value">“fill_parent”</span>
- <span class="attribute">android:orientation</span>=<span class="attribute-value">“vertical”</span> <span class="tag">></span>
-
- <span class="tag"><</span><span class="tag-name">Button</span>
- <span class="attribute">android:layout_width</span>=<span class="attribute-value">“fill_parent”</span>
- <span class="attribute">android:layout_height</span>=<span class="attribute-value">“wrap_content”</span>
- <span class="attribute">android:text</span>=<span class="attribute-value">“scroll”</span>
- <span class="attribute">android:onClick</span>=<span class="attribute-value">“scroll”</span> <span class="tag">/></span>
-
- <span class="tag"><</span><span class="tag-name">com.wb.MyViewGroup</span>
- <span class="attribute">xmlns:android</span>=<span class="attribute-value">“http://schemas.android.com/apk/res/android”</span>
- <span class="attribute">android:layout_width</span>=<span class="attribute-value">“fill_parent”</span>
- <span class="attribute">android:layout_height</span>=<span class="attribute-value">“fill_parent”</span>
- <span class="attribute">android:orientation</span>=<span class="attribute-value">“vertical”</span> <span class="attribute">android:id</span>=<span class="attribute-value">“@+id/myviewGroup”</span><span class="tag">></span>
-
- <span class="tag"><</span><span class="tag-name">TextView</span>
- <span class="attribute">android:layout_width</span>=<span class="attribute-value">“wrap_content”</span>
- <span class="attribute">android:layout_height</span>=<span class="attribute-value">“fill_parent”</span>
- <span class="attribute">android:background</span>=<span class="attribute-value">“#ff0000”</span>
- <span class="attribute">android:text</span>=<span class="attribute-value">“我在這”</span><span class="tag">/></span>
-
-
- <span class="tag"></</span><span class="tag-name">com.wb.MyViewGroup</span><span class="tag">></span>
-
- <span class="tag"></</span><span class="tag-name">LinearLayout</span><span class="tag">></span>
源代码下载地址:[http://download.csdn.net/detail/c_weibin/4208751](http://download.csdn.net/detail/c_weibin/4208751)
💬 评论