OnDragListener没有收到DRAG_STARTED或DRAG_ENDED,但确实获得了ACTION_DROP

Mar*_*era 6 android drag-and-drop

我遇到了一个奇怪的问题OnDragListener.我的目标视图使ACTION_DROP事件正常并处理它; 但它永远不会收到ACTION_DRAG_STARTEDACTION_DRAG_ENDED事件(事实上它除了掉落之外从未收到任何事件).

可能是什么导致了这个?这是一个问题,因为当掉落发生在目标之外时,我无法处理这种情况.

我发现了这个问题,但答案对我来说并不清楚.任何想法都非常感激.

我的可拖动视图有OnTouchListener:

@Override
public boolean onTouch(View v, MotionEvent ev) {
  switch (ev.getAction() & MotionEvent.ACTION_MASK) {
    case MotionEvent.ACTION_DOWN:
      startPointX = ev.getX();
      startPointY = ev.getY();
      isOnClick = true;
      break;
    case MotionEvent.ACTION_CANCEL:
    case MotionEvent.ACTION_UP:
      if (isOnClick) {
        isOnClick = false;
        // handle single click
      }
      break;
    case MotionEvent.ACTION_MOVE:
      if (isOnClick && movePassesThreshold(ev)) {
        isOnClick = false;
        draggableView.startDrag(...);
      }
      break;
    default:
      break;
  }
  return true;
}
Run Code Online (Sandbox Code Playgroud)

目标视图有OnDragListener:

@Override
public boolean onDrag(View v, DragEvent event) {
  switch (event.getAction()) {
    case DragEvent.ACTION_DRAG_STARTED:
      Log.v(TAG, "drag started");
      break;
    case DragEvent.ACTION_DRAG_ENTERED:
      break;
    case DragEvent.ACTION_DRAG_EXITED:
      break;
    case DragEvent.ACTION_DROP:
      Log.v(TAG, "drop");
      // handle drop
      break;
    case DragEvent.ACTION_DRAG_ENDED:
      Log.v(TAG, "drag ended");
      break;
    default:
      return false;
  }
  return true;
}
Run Code Online (Sandbox Code Playgroud)

Mik*_*ike 6

这是ViewGroup的已知问题:

https://code.google.com/p/android/issues/detail?id=25073

如该链接所述,重写dispatchDragEvent函数对我有用:

@Override
public boolean dispatchDragEvent(DragEvent ev){
    boolean r = super.dispatchDragEvent(ev);
    if (r && (ev.getAction() == DragEvent.ACTION_DRAG_STARTED
            || ev.getAction() == DragEvent.ACTION_DRAG_ENDED)){
        // If we got a start or end and the return value is true, our
        // onDragEvent wasn't called by ViewGroup.dispatchDragEvent
        // So we do it here.
        onDragEvent(ev);
    }
    return r;
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*era 2

我的解决方案是这样的解决方法:当我OnTouchListener获得 ACTION_UP 时,设置一个 1 秒延迟的可运行对象来检查视图是否仍在拖动。如果OnDragListener收到了 drop,则 runable 不执行任何操作;但如果没有,可运行调用将停止拖动以清理并将视图重置到其先前的位置。

case MotionEvent.ACTION_UP:
  if (isOnClick) {
    isOnClick = false;
    // handle single click
  } else if (draggableView.isDragging()) {
    uiHandler.postDelayed(new Runnable() {
      @Override
      public void run() {
        if (draggableView.isDragging()) {
          // Drop never got received, so call stopDrag
          draggableView.stopDrag();
        }
      }
    }, 1000);
  }
  break;
Run Code Online (Sandbox Code Playgroud)