Scroller 的滑动应用详解
来源:互联网 发布:有利网 骗局知乎 编辑:程序博客网 时间:2024/05/21 05:17
最近研究了一下qq中listview 滑动出现删除按钮的操作,找到了一个SwipeMenuListView的类库,于是认真的研读了一下代码,确实有很多可学习的知识,其中有一个地方用到了ScrollerCompat这个类,之前确实没有接触过,所以认知学习了一下,这个类,主要是用来支持自动滑动的,其中用到了几个重要的方法:
1、public void startScroll (int startX, int startY, int dx, int dy, int duration)
这个方法其实网上有一堆的详细介绍,但是我发现对几个参数的介绍分歧很大,当时我看的时候确实很困惑,所以仔细研究了一下源码,确定了正确的答案,下面分享给大家,先看一下源码:
/** * Start scrolling by providing a starting point and the distance to travel. * 翻译:通过设置一个起始点和移动距离来启动一个滚动 * @param startX Starting horizontal scroll offset in pixels. Positive * numbers will scroll the content to the left. *翻译:startX代表水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动,也就是x轴起始位置 * @param startY Starting vertical scroll offset in pixels. Positive numbers * will scroll the content up. * 翻译:startY代表垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动 * @param dx Horizontal distance to travel. Positive numbers will scroll the * content to the left. * 翻译:dx 代表水平方向的滑动距离,正值表明向左滑动 * @param dy Vertical distance to travel. Positive numbers will scroll the * content up. * 翻译:dy 代表垂直方向的滑动距离,正值表明向上滑动 * @param duration Duration of the scroll in milliseconds. * 翻译:整个滑动过程所经历的滑动时间,单位毫秒 */ 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; }
首先,这个方法我需要强调一下,网上有些人说dx,dy代表终点位置,我想现在我把源代码展示出来了,大家看一下mFinalX = startX + dx;也应该能够看明白是一个偏移量,也就是移动距离。需要提醒一下 ,我发现SwipeMenuListView的作者也理解错了,将dx理解成终点了,大家用的时候可以注意一下,但是不影响使用。
另外,此处值得正负和轴的方向正好相反,也就是说,如果想向右滑动,则需要设定为
startScroll(负数, 0, 负数, 0, int duration);startX和dx(或startY和dy)正负号一定要统一。
最后 duration代表的是整个移动过程的总时间,默认250ms,不是每一帧移动的时间间隔,网上有的朋友解释的不正确。
2、 public boolean computeScrollOffset()这个方法要明确一点是,是用来判断整个滚动过程是否完全走完,如果走完的返回false,否则返回true,网上有的解释正好相反,大家看一下下面的源代码应该会一目了然。
/** * Call this when you want to know the new location. If it returns true, * the animation is not yet finished. loc will be altered to provide the * new location. */ 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、public void scrollTo(int x, int 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 * 滚动到的X位置 * @param y the y position to scroll to * 滚动到的Y位置 */ 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(); } } }
4、public void computeScroll() 这个方法没有源码,是一个空方法,需要自己来重写。在试图重绘的时候回调用这个方法,就是onDraw()里面调用。
下面给大家简单介绍一下应用:
分一下三步:
第一步:创建ScrollerCompat对象
mScroller= ScrollerCompat.create(getContext(),mInterpolator);//mInterpolator可以省略就是动画效果
第二步:重写computeScroll()
computeScroll(){ if (mScroller.computeScrollOffset()) { //此处一定要进行判断,否则后面调用 postInvalidate();会陷入死循环,无限刷新,导致死机 // 产生了动画效果,根据当前值 每次滚动一点 scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); //让试图移动到指定位置 postInvalidate(); //不可省略,让onDraw继续调用本方法,类似递归 } }
第三步:手动启动滚动
startScroll (0, 0, 200, 0, 350); postInvalidate();//此处需要手动调用刷新,否则不会看到移动效果
- Scroller 的滑动应用详解
- Scroller应用:ListView滑动删除
- Scroller应用:ListView滑动删除
- Scroller 及滑动机制 详解
- Scroller实现View的滑动
- 滑动Scroller
- Android中Scroller实现弹性滑动的原理和实例应用
- Android View 的弹性滑动: Scroller使用说明
- 使用Scroller实现View的弹性滑动
- 通过Scroller实现View的流畅滑动
- 利用Scroller实现自己的滑动布局
- Android中Scroller的应用
- Scroller的fling方法详解
- Android Scroller类详解--实现View内容弹性滑动
- Scroller详解
- android滑动之Scroller
- scroller滑动到底部
- android滑动之Scroller
- 10005---海量数据排序总结
- IOS 设置icon 出现的bug The app icon set named "AppIcon" did not have any applicable content.
- C#中增加弹出对话框控件的方法
- null 为什么可以被转换成任意引用类型?
- 高级编程之目录(二)
- Scroller 的滑动应用详解
- SVG pointer-events属性
- "互联网+"系列(10) 腾讯:众创空间
- ZOJ1037-Gridland
- java基础篇--01<基础>
- bootstrap3 兼容IE8浏览器
- Linux查看进程运行的完整路径方法
- 发送手机短信的倒计时
- javascript 传递参数中带加号自动变成了空格的解决方法