ACTION_CANCEL同时触摸

我有以下类代表一个可触摸的视图,并绘制一个滑动条。

public class SlideBar extends View { private int progress; private int max; private Paint background; private Paint upground; private RectF bar; private boolean firstDraw; public SlideBar(Context context, AttributeSet attrs) { super(context, attrs); progress = 0; upground = new Paint(); upground.setColor(Color.parseColor("#C2296C")); background = new Paint(); background.setColor(Color.parseColor("#777777")); } private void onFirstDraw() { max = getWidth(); bar = new RectF(0, 19, max, 21); } public void onDraw(Canvas canvas) { if (!firstDraw) { onFirstDraw(); progress = max; firstDraw = true; } canvas.save(); canvas.drawRoundRect(bar, 5, 5, background); canvas.drawCircle(progress, 20, 9, upground); canvas.restore(); } public void setValue(int value) { progress = value; } public boolean onTouchEvent(MotionEvent evt) { System.out.println(evt.getAction()); progress = (int) evt.getX(); invalidate(); return false; } } 

但是,当触摸并拖动它时,我收到一个ACTION_DOWN,一些ACTION_MOVEs然后收到一个ACTION_CANCEL并没有进一步的事件

为什么会发生? 我不想取消事件并使其保持拖动状态。

Solutions Collecting From Web of "ACTION_CANCEL同时触摸"

ACTION_CANCEL在父视图接pipe其子视图之一时发生。

看看围绕ViewGroup.onInterceptTouchEvent(MotionEvent)方法的文档。 从链接:

  1. 您将在这里收到停机事件。
  2. down事件将由该视图组的子项处理,或者由您自己的onTouchEvent()方法处理; 这意味着你应该实现onTouchEvent()返回true,所以你将继续看到手势的其余部分(而不是寻找一个父视图来处理它)。 而且,通过从onTouchEvent()返回true,您将不会在onInterceptTouchEvent()中接收到任何以下事件,并且所有的触摸处理都必须像在正常情况下一样发生在onTouchEvent()上。
  3. 只要你从这个函数返回false,每一个下面的事件(直到并包括最后一个)都会在这里被传递,然后被传递到目标的onTouchEvent()。
  4. 如果您从这里返回true,则不会收到以下任何事件:目标视图将收到相同的事件,但操作为ACTION_CANCEL,所有其他事件将传递到您的onTouchEvent()方法,而不再显示在此处

父容器将拦截您的触摸事件时会发生这种情况。 任何重写ViewGroup.onInterceptTouchEvent(MotionEvent)的ViewGroup可以做到这一点(例如ScrollView或ListView)。

处理这个问题的正确方法是在您认为需要保留运动事件时,在父视图中调用ViewParent.requestDisallowInterceptTouchEvent(boolean)方法。

下面是一个简单的例子(attemptClaimDrag方法来自android源代码):

 /** * Tries to claim the user's drag motion, and requests disallowing any * ancestors from stealing events in the drag. */ private void attemptClaimDrag() { //mParent = getParent(); if (mParent != null) { mParent.requestDisallowInterceptTouchEvent(true); } } @Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { if (iWantToKeepThisEventForMyself(event)) { attemptClaimDrag(); } //your logic here } else { //your logic here } }