项目中用到了大神写的Android 带你从源码的角度解析Scroller的滚动实现原理,记录一下,加强记忆

网址:http://blog.csdn.net/xiaanming/article/details/20934541

滑动:

1.基本

scrollTo,滚动的是控件的内容

/**     * 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();            }        }    } /**     * The offset, in pixels, by which the content of this view is scrolled     * horizontally.     * {@hide}     */    @ViewDebug.ExportedProperty(category = "scrolling")    protected int mScrollX;


2.Scroller

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;    }
startScroll设置一些初始参数

2.

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 <= 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;    }
每次调用时,计算此时离滑动开始的时间,计算这段时间里应该滑动的距离,赋值给mCurrX和MCurrY,若时间到了,就赋值mFinished为true,下次再调用时,直接返回false.

3.View中方法,此方法在每次绘制view的时候调用,所以可以这边调用invalidate(),一直循环

</pre><pre name="code" class="java"> @Override    public void computeScroll() {        if (scroller.computeScrollOffset()) {            mParentView.scrollTo(scroller.getCurrX(), 0);            invalidate();                    }         super.computeScroll();    }

Touch滑动:

onTouch和onTouchEvent

dispatchTouchEvent中调用onTouch,

onTouch返回true,将不执行onTouchEvent


 MotionEvent cancelEvent = MotionEvent.obtain(event);                        cancelEvent                                .setAction(MotionEvent.ACTION_CANCEL                                        | (event.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT));                        v.onTouchEvent(cancelEvent);
可以结束接下来的一系列动作,解决点击事件和滑动的冲突,在滑动的时候屏蔽点击事件


view跟随手势滑动,在move事件中先判断是否符合符合滑动,符合的设置标志位为ture,接下来的一系列滑动都根据手指滑动距离,来让view滑动,知道up事件发生,重置标志位为false。





更多相关文章

  1. Android客户端三步完成支付宝支付SDK接入
  2. Android(安卓)手势基础 GestureDetector
  3. Android(安卓)AIDL的实现
  4. Android在绘制View之前计算其高度 / 宽度
  5. Android(安卓)Material Design新UI控件使用大全 三
  6. Android(安卓)壁纸设置_01
  7. Android(安卓)Studio使用AIDL技术进行SDK开发
  8. Android(安卓)Audio代码分析5 - 函数getAudioSessionId
  9. Android定时器Timer.schedule

随机推荐

  1. 高版本Android如何利用反射调用系统隐藏
  2. Android自定义组件之ListPopWindow
  3. Android(安卓)PopupWindow with ListView
  4. Android中的Apk的加固(加壳)原理解析和实
  5. android animation 补充
  6. 移动互联网人丁凋零的苦果早已种下
  7. [置顶] Android照相功能驱动层中HAL的实
  8. 开放的安卓系统遇上了麻烦
  9. 【souapp搜应用】:可牛杀毒软件连android
  10. [Android]WebOfCam,远程访问手机的摄像头,