@Override
  public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
    final RecyclerView.ViewHolder draggingItem = mDraggingItem;

    if (draggingItem == null || draggingItem.getItemId() != mDraggingItemId) {
      return;
    }

    final RecyclerView.ViewHolder swapTargetItem =
        RecyclerViewDragDropManager.findSwapTargetItem(
            mRecyclerView, draggingItem, mDraggingItemId, mTranslationY, mRange);

    // reset Y-translation if the swap target has changed
    if ((mSwapTargetItem != swapTargetItem) && (mSwapTargetItem != null)) {
      setItemTranslationY(mRecyclerView, mSwapTargetItem, 0.0f);
    }

    if (swapTargetItem != null) {
      mReqTranslationPhase = calculateTranslationPhase(draggingItem, swapTargetItem);

      if (mSwapTargetItem != swapTargetItem) {
        mCurTranslationPhase = mReqTranslationPhase;
      } else {
        // interpolate to make it moves smoothly
        mCurTranslationPhase =
            calculateCurrentTranslationPhase(mCurTranslationPhase, mReqTranslationPhase);
      }

      updateSwapTargetTranslation(draggingItem, swapTargetItem, mCurTranslationPhase);
    }

    mSwapTargetItem = swapTargetItem;
  }
  @Override
  public void onViewRecycled(VH holder) {
    if (isDragging()) {
      if (holder == mDraggingItem) {
        if (LOCAL_LOGI) {
          Log.i(TAG, "a view holder object which is bound to currently dragging item is recycled");
        }
        mDraggingItem = null;
        mDragDropManager.onDraggingItemViewRecycled();
      }
    }

    super.onViewRecycled(holder);
  }
  @Override
  public void onBindViewHolder(VH holder, int position) {
    if (isDragging()) {
      final long itemId = holder.getItemId();

      final int origPosition =
          convertToOriginalPosition(
              position, mDraggingItemInitialPosition, mDraggingItemCurrentPosition);

      if (itemId == mDraggingItemId && holder != mDraggingItem) {
        if (mDraggingItem == null) {
          if (LOCAL_LOGI) {
            Log.i(TAG, "a new view holder object for the currently dragging item is assigned");
          }
          mDraggingItem = holder;
          mDragDropManager.onNewDraggingItemViewBinded(holder);
        } else {
          Log.e(TAG, "an another view holder object for the currently dragging item is assigned");
        }
      }

      int flags = RecyclerViewDragDropManager.STATE_FLAG_DRAGGING;

      if (itemId == mDraggingItemId) {
        flags |= RecyclerViewDragDropManager.STATE_FLAG_IS_ACTIVE;
      }
      if (mDraggableRange.checkInRange(position)) {
        flags |= RecyclerViewDragDropManager.STATE_FLAG_IS_IN_RANGE;
      }

      safeUpdateFlags(holder, flags);
      super.onBindViewHolder(holder, origPosition);
    } else {
      safeUpdateFlags(holder, 0);
      super.onBindViewHolder(holder, position);
    }
  }
 protected boolean isDragging() {
   return mDragDropManager.isDragging();
 }
 private void cancelDrag() {
   if (mDragDropManager != null) {
     mDragDropManager.cancelDrag();
   }
 }