最近有点儿纠结listview是怎么实现滑翔运行的(也就是抛出之后,自行滑动一段时间),一开始我以为用到了什么高大上的算法,于是想从源码中查找,结果没发现,不过反而让我发现了一点点新东西。
if (mFlingRunnable == null) {
mFlingRunnable = new FlingRunnable();
}
然后我就对FlingRunnable这个类产生了点兴趣,看看是这样的。
FlingRunnable() {
mScroller = new OverScroller(getContext());
}
一看是用到了OverScroller这个类,之后有某处会调用这个方法
void start(int initialVelocity) {
// 省略
mScroller.fling(0, initialY, 0, initialVelocity,
0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE);
// 省略
}
因此,我就猜测,类似于滑翔运动是基础OverScroller并且与fling这个方法有关,
对于这个方法,是这样介绍的
/**
* Start scrolling based on a fling gesture. The distance traveled will
* depend on the initial velocity of the fling.
*
* @param startX Starting point of the scroll (X)
* @param startY Starting point of the scroll (Y)
* @param velocityX Initial velocity of the fling (X) measured in pixels per
* second.
* @param velocityY Initial velocity of the fling (Y) measured in pixels per
* second
* @param minX Minimum X value. The scroller will not scroll past this point
* unless overX > 0. If overfling is allowed, it will use minX as
* a springback boundary.
* @param maxX Maximum X value. The scroller will not scroll past this point
* unless overX > 0. If overfling is allowed, it will use maxX as
* a springback boundary.
* @param minY Minimum Y value. The scroller will not scroll past this point
* unless overY > 0. If overfling is allowed, it will use minY as
* a springback boundary.
* @param maxY Maximum Y value. The scroller will not scroll past this point
* unless overY > 0. If overfling is allowed, it will use maxY as
* a springback boundary.
因为是listview,不存在x方向上的变化,因此跟x有关的参数都变成0了
一般来说,因为速度上是有方向的,但在这里可以看到
* @param minY Minimum Y value. The scroller will not scroll past this point
* unless overY > 0. If overfling is allowed, it will use minY as
* a springback boundary.
这在这里,一般情况下,minY都会被设置为0,也就是说,速度方向为负数的情况,只能得到为0的滑动距离。
至于解决方案,在下方讲解会说明。
为了测试滑翔运动是不是用这个类来解决,本博主模仿了一下,并且得到一些数据。
本例子也是基于listview实现的,是为了更加准确的验证滑动距离,还有数据的变化会不会随着listview的停止而停止。
初始的时候,需要有一个手势来获取抛出的速度
private GestureDetector mGestureDetector;
并且要在构造器实现
mGestureDetector = new GestureDetector(context,new MyOnGestureListener());
class MyOnGestureListener extends GestureDetector.SimpleOnGestureListener{
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return false;
}
}
手势要能生效,这个步骤是必不可缺的。
@Override
public boolean onTouchEvent(MotionEvent ev) {
mGestureDetector.onTouchEvent(ev);
return super.onTouchEvent(ev);
}
private class FlingScroller implements Runnable{
OverScroller mFlingScroller;
boolean isRunning;
public FlingScroller(){
mFlingScroller = new OverScroller(getContext());
}
private void postExecute() {
if (isRunning)
post(this);
}
private void start(){
isRunning = true;
postExecute();
}
void withFling( int velocityY) {
int initialY = velocityY < 0 ? Integer.MAX_VALUE : 0;
mFlingScroller.fling(0,initialY,0,velocityY,0, Integer.MAX_VALUE,0,Integer.MAX_VALUE);
}
在这个方法,用来传入一开始的y方向上的速度
如果速度<0,让他的初始值为int的最大值,否则为0
上面调用post(this)后,会执行:
@Override
public void run() {
boolean endAnima = true;
if (mFlingScroller.computeScrollOffset()){
final int startY = mFlingScroller.getStartY();
int currY = startY==Integer.MAX_VALUE ?Integer.MAX_VALUE-mFlingScroller.getCurrY():mFlingScroller.getCurrY();
Log.d("FlingScroller", "currY:" + currY);
endAnima = false;
}
if (!endAnima){
postExecute();
}else {
isRunning = false;
}
}
if (mFlingScroller.computeScrollOffset()){
final int startY = mFlingScroller.getStartY();
int currY = startY==Integer.MAX_VALUE ?Integer.MAX_VALUE-mFlingScroller.getCurrY():mFlingScroller.getCurrY();
Log.d("FlingScroller", "currY:" + currY);
endAnima = false;
}
根据这段做一下测试,用最大速度抛出滑动
if (mFlingScroller.computeScrollOffset()){
final int startY = mFlingScroller.getStartY();
int currY = startY==Integer.MAX_VALUE ?Integer.MAX_VALUE-mFlingScroller.getCurrY():mFlingScroller.getCurrY();
Log.d("FlingScroller", "currY:" + currY);
endAnima = false;
}
开头一部分:
10-03 01:24:23.654 18887-18887/com.test.measurelistviewofsliding D/FlingScroller: currY:160
10-03 01:24:23.674 18887-18887/com.test.measurelistviewofsliding D/FlingScroller: currY:480
10-03 01:24:23.698 18887-18887/com.test.measurelistviewofsliding D/FlingScroller: currY:847
10-03 01:24:23.722 18887-18887/com.test.measurelistviewofsliding D/FlingScroller: currY:1243
10-03 01:24:23.750 18887-18887/com.test.measurelistviewofsliding D/FlingScroller: currY:1637
10-03 01:24:23.774 18887-18887/com.test.measurelistviewofsliding D/FlingScroller: currY:2042
10-03 01:24:23.802 18887-18887/com.test.measurelistviewofsliding D/FlingScroller: currY:2441
中间一部分:
10-03 01:24:24.374 18887-18887/com.test.measurelistviewofsliding D/FlingScroller: currY:9149
10-03 01:24:24.402 18887-18887/com.test.measurelistviewofsliding D/FlingScroller: currY:9356
10-03 01:24:24.422 18887-18887/com.test.measurelistviewofsliding D/FlingScroller: currY:9541
10-03 01:24:24.454 18887-18887/com.test.measurelistviewofsliding D/FlingScroller: currY:9743
10-03 01:24:24.526 18887-18887/com.test.measurelistviewofsliding D/FlingScroller: currY:10260
10-03 01:24:24.550 18887-18887/com.test.measurelistviewofsliding D/FlingScroller: currY:10417
10-03 01:24:26.054 18887-18887/com.test.measurelistviewofsliding D/FlingScroller: currY:14350
10-03 01:24:26.078 18887-18887/com.test.measurelistviewofsliding D/FlingScroller: currY:14356
10-03 01:24:26.102 18887-18887/com.test.measurelistviewofsliding D/FlingScroller: currY:14362
10-03 01:24:26.126 18887-18887/com.test.measurelistviewofsliding D/FlingScroller: currY:14366
10-03 01:24:26.154 18887-18887/com.test.measurelistviewofsliding D/FlingScroller: currY:14369
10-03 01:24:26.178 18887-18887/com.test.measurelistviewofsliding D/FlingScroller: currY:14371
10-03 01:24:26.202 18887-18887/com.test.measurelistviewofsliding D/FlingScroller: currY:14372
10-03 01:24:26.226 18887-18887/com.test.measurelistviewofsliding D/FlingScroller: currY:14372
OverScroller还有一个比较重要的方法。
/**
* The amount of friction applied to flings. The default value
* is {@link ViewConfiguration#getScrollFriction}.
*
* @param friction A scalar dimension-less value representing the coefficient of
* friction.
*/
public final void setFriction(float friction) {
mScrollerX.setFriction(friction);
mScrollerY.setFriction(friction);
}
public static float getScrollFriction() {
return SCROLL_FRICTION;
}
/**
* The coefficient of friction applied to flings/scrolls.
*/
private static final float SCROLL_FRICTION = 0.015f;
源码下载:https://github.com/q742972035/measurelistviewofsliding