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并没有进一步的事件

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

  • 如何扩展视图的触摸区域
  • 带onClick和onLongClick的Android onTouch
  • 如何编写多点触控
  • 如何在Galaxy Nexus等设备上隐藏软触button
  • RecyclerView + CardView +触摸反馈
  • jQuery拖放触摸设备(iPad,Android)
  • Android:如何确定一个触摸事件是否在一个圆圈?
  • 如何以编程方式触发Android中的触摸事件?
  • 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 } }