private void handleActionUp(MotionEvent event) {
   if (whichCardOnTouch == -1 || !isTouchOnCard) return;
   long pressDuration = System.currentTimeMillis() - mPressStartTime;
   computeVelocity();
   if (!isDisplaying
       && ((event.getY() - firstDownY < 0
               && (Math.abs(event.getY() - firstDownY) > mMoveDistanceToTrigger))
           || (yVelocity < 0
               && Math.abs(yVelocity) > mMinVelocity
               && Math.abs(yVelocity) > Math.abs(xVelocity)))) {
     displayCard(whichCardOnTouch);
   } else if (!isDisplaying
       && pressDuration < MAX_CLICK_TIME
       && // means click
       distance(firstDownX, firstDownY, event.getX(), event.getY()) < MAX_CLICK_DISTANCE) {
     displayCard(whichCardOnTouch);
   } else if (!isDisplaying
       && isDragging
       && ((event.getY() - firstDownY > 0)
           || Math.abs(event.getY() - firstDownY) < mMoveDistanceToTrigger)) {
     hideCard(whichCardOnTouch);
   } else if (isDisplaying) {
     float currentY = ViewHelper.getY(getChildAt(mDisplayingCard));
     if (currentY < mMarginTop || currentY < (mMarginTop + mMoveDistanceToTrigger)) {
       ObjectAnimator.ofFloat(getChildAt(mDisplayingCard), "y", currentY, mMarginTop)
           .setDuration(mDuration)
           .start();
     } else if (currentY > (mMarginTop + mMoveDistanceToTrigger)) {
       hideCard(mDisplayingCard);
     }
   }
   isTouchOnCard = false;
   deltaY = 0;
   isDragging = false;
 }
  private boolean handleActionDown(MotionEvent event) {
    boolean isConsume = false;
    mPressStartTime = System.currentTimeMillis();
    firstDownY = downY = event.getY();
    firstDownX = event.getX();
    int childCount = isExistBackground ? (mChildCount - 1) : mChildCount;
    // Judge which card on touching
    if (!isDisplaying && downY > (getMeasuredHeight() - mChildCount * mTitleBarHeightNoDisplay)) {
      for (int i = 1; i <= mChildCount; i++) {
        if (downY
            < (getMeasuredHeight()
                - mChildCount * mTitleBarHeightNoDisplay
                + mTitleBarHeightNoDisplay * i)) {
          whichCardOnTouch = i - 1;
          isTouchOnCard = true;
          if (mOnDisplayOrHideListener != null)
            mOnDisplayOrHideListener.onTouchCard(whichCardOnTouch);
          isConsume = true;
          break;
        }
      }
      mTouchingViewOriginY = ViewHelper.getY(getChildAt(whichCardOnTouch));
    } else if (isDisplaying
        && downY > (getMeasuredHeight() - (childCount - 1) * mTitleBarHeightDisplay)) {
      hideCard(mDisplayingCard);
    } else if (isDisplaying
        && downY > mMarginTop
        && mDisplayingCard >= 0
        && downY < getChildAt(mDisplayingCard).getMeasuredHeight() + mMarginTop) {
      whichCardOnTouch = mDisplayingCard;
      isTouchOnCard = true;
    } else if (isDisplaying
        && (downY < mMarginTop
            || (mDisplayingCard >= 0
                && (downY > mMarginTop + getChildAt(mDisplayingCard).getMeasuredHeight())))) {
      hideCard(mDisplayingCard);
    }

    if (isExistBackground && whichCardOnTouch == 0) {
      isTouchOnCard = false;
    }
    return isConsume;
  }
 public void hide(int index) {
   if (isExistBackground) index++;
   if (index != mDisplayingCard || !isDisplaying) return;
   if (index >= mChildCount) throw new IllegalArgumentException("Card Index Not Exist");
   hideCard(index);
 }