我使用SurfaceView
绘制触摸作为我的应用的叠加层。我希望我的其他View
能够在SurfaceView
的同时响应触摸事件,因此在包含它们的ViewGroup
中我添加了
MyViewGroup:
@Override
public boolean onInterceptTouchEvent(MotionEvent motionEvent){
mSurfaceView.onTouchEvent(motionEvent);
return false;
}
由于SurfaceView
位于其他视图后面,因此效果很好。其顶部的SurfaceView
和View
都会收到MotionEvent
。
SurfaceView
然后进一步将事件转发给呈现它的线程。
MySurfaceView:
@Override
public boolean onTouchEvent(MotionEvent motionEvent) {
if (mThreadHandler != null){
mThreadHandler.sendMotionEvent(motionEvent);
}
return true;
}
然后当我的渲染线程收到它运行的消息时:
MyRenderThread:
private void handleMotionEvent(MotionEvent motionEvent){
switch (motionEvent.getAction()){
case MotionEvent.ACTION_DOWN:
float x = motionEvent.getX(); // Breakpoint 1
float x2 = motionEvent.getX(); // Breakpoint 2
float x3 = motionEvent.getX(); // Breakpoint 3
path.moveTo(motionEvent.getX(), motionEvent.getY());
break;
case MotionEvent.ACTION_MOVE:
path.lineTo(motionEvent.getX(),motionEvent.getY());
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
// do nothing
break;
default:
break;
}
}
当我在调试模式下运行此代码并在ViewGroup
上扫描x
时,x2
和x3
的值都不同。我怀疑这是因为UI线程在被MyRenderThread
使用之前重新使用了MotionEvent。我该如何解决这个问题?
糟糕的解决方案是将每个MotionEvent
复制为新对象并将其传递给MyRenderThread
,但这需要很多对象创建/销毁。
答案 0 :(得分:1)
MotionEvent.obtain(MotionEvent ev)
将从池中返回MotionEvent
,它是输入事件的副本。
MyViewGroup:
@Override
public boolean onInterceptTouchEvent(MotionEvent motionEvent){
mSurfaceView.fowardTouchEvent(MotionEvent.obtain(motionEvent);
return false;
}
MySurfaceView:
public void forwardTouchEvent(MotionEvent motionEvent){
if (scratchpadThreadHandler != null){
scratchpadThreadHandler.sendMotionEvent(motionEvent);
}
}
MyRenderThread:
private void handleMotionEvent(MotionEvent motionEvent){
switch (motionEvent.getAction()){
case MotionEvent.ACTION_DOWN:
float x = motionEvent.getX(); // Breakpoint 1
float x2 = motionEvent.getX(); // Breakpoint 2
float x3 = motionEvent.getX(); // Breakpoint 3
path.moveTo(motionEvent.getX(), motionEvent.getY());
break;
case MotionEvent.ACTION_MOVE:
path.lineTo(motionEvent.getX(),motionEvent.getY());
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
// do nothing
break;
default:
break;
}
motionEvent.recycle(); // Mark this MotionEvent as available for recycling.
}
这样每个事件仍然被复制(不知道该怎么办),但至少会重用这些对象。