Scroll类之所以不好理解是因为没有搞清楚View的绘制流程。

1)简单来讲 viewgroup重绘时依次会调用  dispatchDraw -- drawChild --child.computeScroll()。

computeScroll是一个空函数,可以在里面写代码。

2)Scroller类一些api:

mScroller.getCurrX() //获取mScroller当前水平滚动的位置
mScroller.getCurrY() //获取mScroller当前竖直滚动的位置
mScroller.getFinalX() //获取mScroller最终停止的水平位置
mScroller.getFinalY() //获取mScroller最终停止的竖直位置
mScroller.setFinalX(int newX) //设置mScroller最终停留的水平位置,没有动画效果,直接跳到目标位置
mScroller.setFinalY(int newY) //设置mScroller最终停留的竖直位置,没有动画效果,直接跳到目标位置 //滚动,startX, startY为开始滚动的位置,dx,dy为滚动的偏移量, duration为完成滚动的时间
mScroller.startScroll(int startX, int startY, int dx, int dy) //使用默认完成时间250ms
mScroller.startScroll(int startX, int startY, int dx, int dy, int duration) mScroller.computeScrollOffset() //返回值为boolean,true说明滚动尚未完成,false说明滚动已经完成。这是一个很重要的方法,通常放在View.computeScroll()中,用来判断是否滚动是否结束。

其中非常重要的startScroll()和computeScrollOffset()函数。

startScroll函数的功能是设置一些值,最重要的值是设置了一个滚动开始时间和持续时间,其源码如下:

    public void startScroll(int startX, int startY, int dx, int dy, int duration) {
mMode = SCROLL_MODE;
mFinished = false;
mDuration = duration;
mStartTime = AnimationUtils.currentAnimationTimeMillis();
mStartX = startX;
mStartY = startY;
mFinalX = startX + dx;
mFinalY = startY + dy;
mDeltaX = dx;
mDeltaY = dy;
mDurationReciprocal = 1.0f / (float) mDuration;
}

computeScrollOffset()是用来计算当前时间点理论上能够滚到的x,y坐标。

如果滚动持续时间到了则返回false,否则返回true并计算坐标。mCurrX和mCurrY得到更新。源码如下:

    public boolean computeScrollOffset() {
if (mFinished) {
return false;
} int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime); if (timePassed < mDuration) {
switch (mMode) {
case SCROLL_MODE:
float x = timePassed * mDurationReciprocal; if (mInterpolator == null)
x = viscousFluid(x);
else
x = mInterpolator.getInterpolation(x); mCurrX = mStartX + Math.round(x * mDeltaX);
mCurrY = mStartY + Math.round(x * mDeltaY);
break;
case FLING_MODE:
final float t = (float) timePassed / mDuration;
final int index = (int) (NB_SAMPLES * t);
float distanceCoef = 1.f;
float velocityCoef = 0.f;
if (index < NB_SAMPLES) {
final float t_inf = (float) index / NB_SAMPLES;
final float t_sup = (float) (index + 1) / NB_SAMPLES;
final float d_inf = SPLINE_POSITION[index];
final float d_sup = SPLINE_POSITION[index + 1];
velocityCoef = (d_sup - d_inf) / (t_sup - t_inf);
distanceCoef = d_inf + (t - t_inf) * velocityCoef;
} mCurrVelocity = velocityCoef * mDistance / mDuration * 1000.0f; mCurrX = mStartX + Math.round(distanceCoef * (mFinalX - mStartX));
// Pin to mMinX <= mCurrX <= mMaxX
mCurrX = Math.min(mCurrX, mMaxX);
mCurrX = Math.max(mCurrX, mMinX); mCurrY = mStartY + Math.round(distanceCoef * (mFinalY - mStartY));
// Pin to mMinY <= mCurrY <= mMaxY
mCurrY = Math.min(mCurrY, mMaxY);
mCurrY = Math.max(mCurrY, mMinY); if (mCurrX == mFinalX && mCurrY == mFinalY) {
mFinished = true;
} break;
}
}
else {
mCurrX = mFinalX;
mCurrY = mFinalY;
mFinished = true;
}
return true;
}

3)通过1、2我们可以知道如果要实现平滑滚动则需要在computeScroll函数里调用computeScrollOffset()来更新Scroller里面的mCurrX 和mCurrY,然后利用

scrollTo(mCurrX, mCurrY) 来让View的x、y坐标滚动到指定位置。此时并不一定会导致view重绘,手动调用postInvalidate()自上而下重绘view树。

注意scrollTo只会导致该view的内容发生偏移,并不会导致该view的位置偏移。比如对Button进行scrollTo 会导致Button里面的text发生偏移,而Button的位置不会发生偏移。

4) 有了上面的分析后下面是一段小实例,单击按钮后,按钮会慢慢下移。

CustomView.java:

public class CustomView extends LinearLayout {

    private Scroller mScroller = null;
private Context mContext; public CustomView(Context context) {
super(context);
mContext = context;
init();
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
init();
} private void init() {
if (mScroller == null) {
mScroller = new Scroller(mContext);
}
this.setOrientation(VERTICAL);
Button btn = new Button(mContext);
btn.setText("按钮");
LayoutParams params = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
this.addView(btn, params);
this.setBackgroundColor(Color.YELLOW);
} //调用此方法设置滚动到目标位置
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.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), dx, dy, 10000);
invalidate();
} @Override
public void computeScroll() {
// TODO Auto-generated method stub //查看是否滚动结束了,true表示没有结束
if (mScroller.computeScrollOffset()) {
//调用view的滚动函数,进行实际滚动。
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
//只有postInvalidate了才能循环刷新。
postInvalidate();
}
super.computeScroll();
}
}

MainActivity.java:

public class MainActivity extends Activity {

    @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
final CustomView view = new CustomView(this);
setContentView(view);
     //给button添加onClick监听
view.getChildAt(0).setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
// TODO Auto-generated method stub
view.smoothScrollBy(0, -100);
}
});
} }

参考网页:http://www.cnblogs.com/PDW-Android/p/3653253.html

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

http://www.open-open.com/lib/view/open1328834050046.html

Scroller类的使用总结的更多相关文章

  1. 简单的ViewPager了解Scroller类

    View滑动是自定义ViewGroup中十分常见的一个功能.Android提供了多种View滑动的方法. layout方法 offsetLeftAndRight()与offsetTopAndBotto ...

  2. 在Android中动画移动一个View的位置,采用Scroller类实现Android动画之 View移动

    在Android中动画移动一个View的位置,采用Scroller类实现 今天说最近自己遇到的一个问题,就是要用动画效果来移动一个VIew的位置. 这个具体的情况是,需要做一个SlidingMenu的 ...

  3. Android中滑屏实现----手把手教你如何实现触摸滑屏以及Scroller类详解

    前言:  虽然本文标题的有点标题党的感觉,但无论如何,通过这篇文章的学习以及你自己的实践认知,写个简单的滑屏小 Demo还是just so so的. 友情提示: 在继续往下面读之前,希望您对以下知识点 ...

  4. Android Scroller类的详细分析

    尊重原创作者,转载请注明出处: http://blog.csdn.net/gemmem/article/details/7321910 Scroller这个类理解起来有一定的困难,刚开始接触Scrol ...

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

    在android学习中,动作交互是软件中重要的一部分,其中的Scroller就是提供了拖动效果的类,在网上,比如说一些Launcher实现滑屏都可以通过这个类去实现..   例子相关博文:Androi ...

  6. Android 仿 窗帘效果 和 登录界面拖动效果 (Scroller类的应用) 附 2个DEMO及源码

    在android学习中,动作交互是软件中重要的一部分,其中的Scroller就是提供了拖动效果的类,在网上,比如说一些Launcher实现滑屏都可以通过这个类去实现.下面要说的就是上次Scroller ...

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

    在上一篇中介绍了View类的scrollTo和scrollBy两个方法,对这两个方法不太了解的朋友能够先看<自己定义View及ViewGroup> scrollTo和scrollBy尽管实 ...

  8. Android VelocityTracker类和Scroller类

    VelocityTracker类:用于跟踪触屏事件的速度,通常使用VelocityTracker的步骤如下: static VelocityTracker obtain():获取一个VelocityT ...

  9. Android 仿 窗帘效果 和 登录界面拖动效果 (Scroller类的应用) 附 2个DEMO及源代码

    在android学习中,动作交互是软件中重要的一部分.当中的Scroller就是提供了拖动效果的类,在网上.比方说一些Launcher实现滑屏都能够通过这个类去实现.以下要说的就是上次Scroller ...

随机推荐

  1. Android为 ContentProvider 提供了那些服务内容?

    ContentProvider 可以调用系统想要共享的内容,安卓为我们提供了哪些和大家共享的东西呢? 官方文档: https://developer.android.com/reference/and ...

  2. LB 负载均衡的层次结构(转)

    http://blog.csdn.net/mindfloating/article/details/51020767 作为后端应用的开发者,我们经常开发.调试.测试完我们的应用并发布到生产环境,用户就 ...

  3. GuavaCache简介(一)

    原文地址 http://blog.csdn.net/guozebo/article/details/51590517 前言 在多线程高并发场景中往往是离不开cache的,需要根据不同的应用场景来需要选 ...

  4. git 打tag

    查看已有tag git tag 创建新的tag git tag <version or tagname> -m <tag description> 例如创建一个版本1.0.0的 ...

  5. STS(spring tool suite)修改默认编码

    安装STS后首先要做的修改默认编码: 1.windows--perferences--general--workspace,Text file encoding设置成utf-8 2.windows-- ...

  6. nginx 安装第三方 模块

    查看nginx在安装时开启了哪些模块 如果你nginx是rpm包安装的,直接用如下命令nginx -V 如果你是源码包编译安装,假如你的安装路径是/usr/local/nginx,那么你可以使用: / ...

  7. C语言把字符串转换为数字

    C当中有一些函数专门用于把字符串形式转换成数值形式. printf()函数和sprintf()函数 -->通过转换说明吧数字从数字形式转换为字符串形式: scanf()函数把输入字符串转换为数值 ...

  8. asp:FileUpload 控件上传多文件

    <asp:FileUpload runat="server" ID="imgUpload" AllowMultiple="true" ...

  9. BZOJ 3631 松鼠的新家 树上差分

    我猜会有智障说直接链剖+线段树…(希望没有) From RYC's 课件 然鹅我并不反对树剖...我是智障...QAQ 好吧还是树上差分:设 a[i]=u.a[i+1]=v ++w[u],++w[v] ...

  10. Codeforces Round #532 (Div. 2)- A(思维)

    This morning, Roman woke up and opened the browser with nn opened tabs numbered from 11 to nn. There ...