scrollTo/scrollBy
- 这两个方法都是View的内部方法
- scrollTo和scrollBy只能改变View的内容而不能改变View在布局中的位置。
- 移动方向与笛卡尔坐标轴左右上下是相反的
- 在滑动过程中,View内部的两个属性mscrollX和mscrollY都可以通过getScrollX和getScrollY方法获得,mscrollX就是View左边缘和View内容左边缘在水平方向的距离。同理,mscrollY就是View上边缘和View内容的上边缘的竖直方向的距离
Scroller
- Scroller就是一个辅助类, 用来帮助进行弹性滑动。具体使用方法如下:
//在需要改动的view中
Scroller scroller = new Scroller(mContext);
//缓慢滚动到指定位置
private void smoothScrollTo(int destX, int destY){
int scrollX = getScrollX(); //获取当前的mscrollX
int scrolloY = getScrollY(); //获取当前的mscrollY
int deltaX = destX - scrollX;
int deltaY = destY - scrollY;
mScroller.startScroll(scrollX, scrollY , deltaX, deltaY,1000);
invalidate();
}
@override
public void computeScroll(){
if ( mScroller.computeScrolljOffset()){
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();
}
}
上面的代码就是如何在自定义的View中添加弹性滑动的效果。在自定义的View初始化时,定义一个Scroller,然后自己添加一个private void smoothScrollTo()
这样一个私有方法,用来被调用来执行滑动效果的。public void computeScroll()
方法在view中本是一个空实现的方法,这个方法在view重绘时,draw方法中会被调用。那上面的代码整个逻辑流程是什么呢?让我们继续往下看。
- Scroller的源码学习
在smoothScrollTo(int destX, int destY)
方法中,整个逻辑流程如下:
- 我们首先利用view的getScrollX方法和getScrollY方法获取到现在view与其内容的偏移距离,
- 接着根据目标偏移距离和当前偏移距离的差值,得到这次目前需要进行得分位移
- 执行
mScroller.startScroll()
方法,输入参数是当前X,Y方向的偏移距离,目标的偏移距离,位移时间。下面介绍下mScroller.startScroll()
方法的源码。主要功能是保存传递的几个参数。
public void startScroll(int startX, int startY,int dx,int dy,int duration){
mMode = SCROLL_MODE;
mFinished = false;
mDurarion = duration;
mStartTime = AnimationUtilesd.currentAnimationTimeMilllis();
mStartX = startX;
mStartY = startY;
mFinalX = startX + dx;
mFinalY = startY + dy;
mDeltaX = dx;
mDeltaY = dy;
mDurationReciprocal = 1.0f /(float) mDuration;
}
- 调用
invalidate()
会导致该View重绘,View在draw()方法中会调用computeScroll()
方法。 - 在
computeScroll()
方法,先调用mScroller.computeScrollOffset()
方法,并判断其返回值。该方法的主要功能就是根据开始的坐标位移,目的坐标位移,当前的时间,总时间来确定此时此刻的位移X Y应该是多少,并赋给mCurrX和mCurrY。public boolean computeScrollOffset(){ ... int timePassed = (int) (AnimationUtils.currentAnimationTimeMills() - mStartTime); if (timePassed < mDuration) { switch(mMode) { case SCROLL_MODE: final float x = mInterpolartor.getInterpolation(timePassed * mDurationReciprocal); mCurrX = mStartX + Math.round(x * mDeltaX); mCurrY = mStartY + Math.round(x * mDeltaY); break; ...... } } return true; }
- 在
computeScrollOffset()
执行完后,在computeScroll
方法中,使用scrollTo
方法位移到刚刚计算出的mCurrX,mCurrY的位置上,然后调用postInvalidate()
方法,再次要求重绘,再次调用draw
方法,从而再次执行computeScroll( )
方法让,从而能够绘制出不同时间在不同位置出现的移动画面。scrollTo(mScroller.getCurrX(),mScroller.getCurrY()); postInvalidate();
网友评论