private float calculateTranslationPhase(
      RecyclerView.ViewHolder draggingItem, RecyclerView.ViewHolder swapTargetItem) {
    final View swapItemView = swapTargetItem.itemView;

    final int pos1 = draggingItem.getLayoutPosition();
    final int pos2 = swapTargetItem.getLayoutPosition();

    CustomRecyclerViewUtils.getDecorationOffsets(
        mRecyclerView.getLayoutManager(), swapItemView, mSwapTargetDecorationOffsets);
    CustomRecyclerViewUtils.getLayoutMargins(swapItemView, mSwapTargetItemMargins);

    final Rect m2 = mSwapTargetItemMargins;
    final Rect d2 = mSwapTargetDecorationOffsets;
    final int h2 = swapItemView.getHeight() + m2.top + m2.bottom + d2.top + d2.bottom;

    final float offsetPx =
        draggingItem.itemView.getTop()
            - mTranslationY; // == -(ViewCompat.getTranslationY(draggingItem.itemView)
    final float phase = (h2 != 0) ? (offsetPx / h2) : 0.0f;

    float translationPhase;

    if (pos1 > pos2) {
      // dragging item moving to upward
      translationPhase = phase;
    } else {
      // dragging item moving to downward
      translationPhase = 1.0f + phase;
    }

    return Math.min(Math.max(translationPhase, 0.0f), 1.0f);
  }
  public SwapTargetItemOperator(
      RecyclerView recyclerView, RecyclerView.ViewHolder draggingItem, ItemDraggableRange range) {
    super(recyclerView, draggingItem);

    mDraggingItemId = mDraggingItem.getItemId();
    mRange = range;

    CustomRecyclerViewUtils.getLayoutMargins(mDraggingItem.itemView, mDraggingItemMargins);
    CustomRecyclerViewUtils.getDecorationOffsets(
        mRecyclerView.getLayoutManager(), mDraggingItem.itemView, mDraggingItemDecorationOffsets);
  }