关于拖移View时的抖动问题(event.getY()的跳跃问题)

在最近的项目中碰到需要用手指控制View移动的需求,实现的过程中发现View会随着手指的移动而抖动,并且抖动程度随着拖动距离的增大而增大。简化代码片段如下

view.setOnTouchListener(new OnTouchListener() {float lastY;@Overridepublic boolean onTouch(View v, MotionEvent event) {if(event.getAction() == MotionEvent.ACTION_DOWN)lastY = event.getY();//获得起始纵坐标if(event.getAction() == MotionEvent.ACTION_MOVE ){//执行这一步时view会发生Y轴上的抖动并且抖动程度会随着ACTION_MOVE的执行次数而加剧view.setTranslationY(event.getY()-lastY);//这一步用来探明抖动的原因来自于event.getY()异常Log.i("Y", event.getY()+"");}}return false;});

笔者将view匀速向上拖移,Log输出如下:

03-28 08:32:26.050: I/Y(2234): 76.7545403-28 08:32:26.210: I/Y(2234): 73.1761703-28 08:32:26.340: I/Y(2234): 75.8234403-28 08:32:26.650: I/Y(2234): 71.1237403-28 08:32:27.100: I/Y(2234): 74.8750803-28 08:32:27.250: I/Y(2234): 70.07107503-28 08:32:27.510: I/Y(2234): 73.9254103-28 08:32:27.650: I/Y(2234): 67.9755103-28 08:32:27.800: I/Y(2234): 74.0244903-28 08:32:27.890: I/Y(2234): 66.93545503-28 08:32:28.530: I/Y(2234): 73.06361403-28 08:32:28.620: I/Y(2234): 65.830103-28 08:32:28.920: I/Y(2234): 71.15369403-28 08:32:29.120: I/Y(2234): 64.84119403-28 08:32:29.830: I/Y(2234): 70.146803-28 08:32:30.070: I/Y(2234): 63.8322

可以看出确实为event.getY()出了问题,,于是翻阅getY()的源码如下:

/*** {@link #getY(int)} for the first pointer index (may be an* arbitrary pointer identifier).** @see #AXIS_Y*/public final float getY() {return nativeGetAxisValue(mNativePtr, AXIS_Y, 0, HISTORY_CURRENT);}由于nativeGetAxisValue()是native方法所以我们无法直接在在eclipse中看到具体的方法定义,不过至少我们知道getY()返回的值是和AXIS_Y有关的,所以继续查阅AXIS_Y的说明,如下:public static final int AXIS_YAdded in API level 12Axis constant: Y axis of a motion event.·For a touch screen, reports the absolute Y screen position of the center of the touch contact area. The units are display pixels.·For a touch pad, reports the absolute Y surface position of the center of the touch contact area. The units are device-dependent; use getMotionRange(int) to query the effective range of values.·For a mouse, reports the absolute Y screen position of the mouse pointer. The units are display pixels.·or a trackball, reports the relative vertical displacement of the trackball. The value is normalized to a range from -1.0 (up) to 1.0 (down).·For a joystick, reports the absolute Y position of the joystick. The value is normalized to a range from -1.0 (up or far) to 1.0 (down or near).从"For a touch screen, reports the absolute Y screen position of the center of the touch contact area"中得知AXIS_Y表示的是触摸点相对于触摸区域的绝对Y轴坐标,也就是pointer相对于所触摸View的absoluteY,读到这里大概就明白了为什么会出现View的抖动问题:

因为View是移动的,在获取相对坐标的过程中,getY()=AXIS_Y=absoluteY+viewTranslationY(这就是为什么抖动程度会随着拖动距离的增加而增加),从Log日志中可以发现,抖动是逐帧间隔形式的,即一次AXIS_Y=absoluteY之后接着便是AXIS_Y=absoluteY+viewTranslationY。由于无法看到nativeGetAxisValue()的具体定义,所以暂时并不清楚造成这种结果的具体原因。

解决办法很简单,只要把getY()换成getRawY()即可,后者的源码获取的是pointer相对于整个screen的绝对坐标,这里就不贴出来了。

分析告诉我们,getX/Y()不适用于绑定在动态组件上的onTouchListener。

困难是人的教科书。

关于拖移View时的抖动问题(event.getY()的跳跃问题)

相关文章:

你感兴趣的文章:

标签云: