页面的滑动
一、scrollTo,scrollBy
这两个方法在View类中
/*** Move the scrolled position of your view. This will cause a call to* {@link #onScrollChanged(int, int, int, int)} and the view will be* invalidated.* @param x the amount of pixels to scroll by horizontally* @param y the amount of pixels to scroll by vertically*/public void scrollBy(int x, int y) {scrollTo(mScrollX + x, mScrollY + y);}/*** Set the scrolled position of your view. This will cause a call to* {@link #onScrollChanged(int, int, int, int)} and the view will be* invalidated.* @param x the x position to scroll to* @param y the y position to scroll to*/public void scrollTo(int x, int y) {if (mScrollX != x || mScrollY != y) {int oldX = mScrollX;int oldY = mScrollY;mScrollX = x;mScrollY = y;invalidateParentCaches();onScrollChanged(mScrollX, mScrollY, oldX, oldY);if (!awakenScrollBars()) {postInvalidateOnAnimation();}}}
首先scrollBy(x,y),是改变量,内部可见调用的scrollTo(mScrollX + x, mScrollY + y); mScrollX 和mScrollY表示的当前View的偏移量。
scrollTo(x,y)并不会使页面滑动,我的理解是它主要的作用就是保持一系列的值,然后通知页面重绘。
二、smoothScrollBy,smoothScrollTo
这两个方法在HorizontalScrollView类中
/*** Like {@link View#scrollBy}, but scroll smoothly instead of immediately.** @param dx the number of pixels to scroll by on the X axis* @param dy the number of pixels to scroll by on the Y axis*/public final void smoothScrollBy(int dx, int dy) {if (getChildCount() == 0) {// Nothing to do.return;}long duration = AnimationUtils.currentAnimationTimeMillis() - mLastScroll;if (duration > ANIMATED_SCROLL_GAP) {final int width = getWidth() - mPaddingRight - mPaddingLeft;final int right = getChildAt(0).getWidth();final int maxX = Math.max(0, right - width);final int scrollX = mScrollX;dx = Math.max(0, Math.min(scrollX + dx, maxX)) - scrollX;mScroller.startScroll(scrollX, mScrollY, dx, 0);postInvalidateOnAnimation();} else {if (!mScroller.isFinished()) {mScroller.abortAnimation();}scrollBy(dx, dy); //调用View的scrollBy(x.y)方法}mLastScroll = AnimationUtils.currentAnimationTimeMillis();}/*** Like {@link #scrollTo}, but scroll smoothly instead of immediately.** @param x the position where to scroll on the X axis* @param y the position where to scroll on the Y axis*/public final void smoothScrollTo(int x, int y) {smoothScrollBy(x - mScrollX, y - mScrollY);}
smoothScrollBy(x,y)方法在判断滑动间隔的时间长短后判定是一蹴而就还是慢慢滑向终点,关键方法是调用View的srcoll(x,y)方法,或借助scroller,这里x,y也是相对改变的值
smoothScrollTo(x.y)这里我只针对x说下他的历程(smoothScrollTo-->smothScrollBy-->scrollBy-->scrollTo),是绝对值 借助一个变量transX
在smoothScrollTo 方法中 transX = 最初值;
在smoothScrollBy 方法中 transX = 最初值 - mScrollX;
在srollBy 方法中 tansX = 最初值 - mScrollX + mScrollX;
在srollTo 方法中 tansX = 最初值 ;
这里的页面滑动我理解的是 我将屏幕比作显示框,当x 为正时,即使显示框向右移动,我们感觉里面显示的内容就好像是左移
当y 为正时,即使显示框向下移动,我们感觉里面显示的内容就好像是上移
此时显示的是一, 当x =500,这里我假设我屏幕宽度是500
Y轴同一个道理
三、Scroller
这里讲它主要是说明View是怎么滑动的,是谁让它滑动的
public boolean computeScrollOffset() {if (mFinished) {return false;}int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);if (timePassed < mDuration) {switch (mMode) {case SCROLL_MODE:final float x = mInterpolator.getInterpolation(timePassed * mDurationReciprocal);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 <= mMaxXmCurrX = Math.min(mCurrX, mMaxX);mCurrX = Math.max(mCurrX, mMinX);mCurrY = mStartY + Math.round(distanceCoef * (mFinalY - mStartY));// Pin to mMinY <= mCurrY <= mMaxYmCurrY = 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;}
而我们在滑动时,通常会加上这么一句代码
@Overridepublic void computeScroll() {if (mScroller.computeScrollOffset()) {scrollTo(mScroller.getCurrX(), 0);postInvalidate();}}
这里我们可以看到,在系统调用startScroll..会促使页面重绘,,然后我们会在computeScroll()方法中会判断是否滑动结束了,没有的话就scrollTo(mScroller.getCurrX(), mScroller.getCurrY());再postInvalidate 去绘制它。
computeScroll()方法里面存在了一个类似与动画取间的东西,把我们要滑向的终点根据during时间长短,一点一点去改变,所以我们获得的currX和currY是慢慢接近我们的目标点的。
所以当我们定好目标点后,一点一点改变,重绘的去绘制,让我们感觉它是在慢慢滑动
嗯,就这样