理解---Android(安卓)向右滑动销毁(finish)Activity, 随着手势的滑动而滑动的效果(大神博客)
16lz
2021-01-26
项目中用到了大神写的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。
更多相关文章
- Android客户端三步完成支付宝支付SDK接入
- Android(安卓)手势基础 GestureDetector
- Android(安卓)AIDL的实现
- Android在绘制View之前计算其高度 / 宽度
- Android(安卓)Material Design新UI控件使用大全 三
- Android(安卓)壁纸设置_01
- Android(安卓)Studio使用AIDL技术进行SDK开发
- Android(安卓)Audio代码分析5 - 函数getAudioSessionId
- Android定时器Timer.schedule