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. spark 熟悉过程

    spark shell 交互 启动:bin 目录下   ./spark-shell  --master local [ ×× ]    --jars ×××.jar   进入[ >> sc ...

  2. 以证书的方式登录ssh

    常常要登录多台Linux服务器,过去在Windows下使用SecureCRT,比较省心,配置还可以放到云盘,实时同步.现在改用MAC貌似就没有那么好用的东西了,每次ssh命令登录都需要输入密码,很烦. ...

  3. Common operators to overload-c++运算符重载的标准语法(全)

    Common operators to overload Most of the work in overloading operators is boiler-plate code. That is ...

  4. srs录制视频时间戳有点问题

    srs2或者srs3目前最新的版本和之前的版本,使用dvr功能录制flv文件.使用本地播放器,如ffplay.potplayer.vlc.KMP和MPV等,都是正常的播放完整视频.但是使用web fl ...

  5. ArcGIS api for javascript-图层控制(图层树)

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  6. 「洛谷5017」「NOIP2018」摆渡车【DP,经典好题】

    前言 在考场被这个题搞自闭了,那个时候自己是真的太菜了.qwq 现在水平稍微高了一点,就过来切一下这一道\(DP\)经典好题. 附加一个题目链接:[洛谷] 正文 虽然题目非常的简短,但是解法有很多. ...

  7. 树莓派安装开源智能家居系统 Domoticz

    前言 最近闲来无事开始折腾自己的智能家居系统,对比了几种比较流行的开源智能家居系统,觉得 Domoticz 更适合,Domoticz的官方中文文档,虽然不是很完善但还是可以参考一下.需要注意的是下文用 ...

  8. 让函数的input、output更"函数化"

    前言 我们都知道函数的基本形式为:output f(input),且先按这种形式进行input与output的分析,我们的input与output可以有更好的设计方式,而我们的output是选择使用r ...

  9. pre 标签 防止 其撑开 div...

    pre 里面 的内容如果不换行,会导致 div 横向 出现 滚动条...加入下列 css可解决! pre{ white-space: pre-wrap; word-wrap: break-word; ...

  10. 07-图5 Saving James Bond - Hard Version (30 分)

    This time let us consider the situation in the movie "Live and Let Die" in which James Bon ...