private boolean onFling(float velocityY) {
    if (getHeight() == 0) {
      return false;
    }

    float velocity = -velocityY / getHeight() * 180f;
    velocity = Math.max(MIN_FLING_VELOCITY, Math.abs(velocity)) * Math.signum(velocity);

    return flingAnimation.fling(velocity);
  }
  protected void animateFold(float to) {
    final float from = getFoldRotation();
    final long duration = (long) Math.abs(ANIMATION_DURATION_PER_ITEM * (to - from) / 180f);

    flingAnimation.stop();

    animator.cancel();
    animator.setFloatValues(from, to);
    animator.setDuration(duration);
    animator.start();
  }
  protected void setFoldRotation(float rotation, boolean isFromUser) {
    if (isFromUser) {
      animator.cancel();
      flingAnimation.stop();
    }

    rotation = Math.min(Math.max(minRotation, rotation), maxRotation);

    foldRotation = rotation;

    final int firstVisiblePosition = (int) (rotation / 180f);
    final float localRotation = rotation % 180f;
    final int totalCount = getCount();

    FoldableItemLayout firstLayout = null;
    FoldableItemLayout secondLayout = null;

    if (firstVisiblePosition < totalCount) {
      firstLayout = getLayoutForItem(firstVisiblePosition);
      firstLayout.setFoldRotation(localRotation);
      onFoldRotationChanged(firstLayout, firstVisiblePosition);
    }

    if (firstVisiblePosition + 1 < totalCount) {
      secondLayout = getLayoutForItem(firstVisiblePosition + 1);
      secondLayout.setFoldRotation(localRotation - 180f);
      onFoldRotationChanged(secondLayout, firstVisiblePosition + 1);
    }

    boolean isReversedOrder = localRotation <= 90f;

    if (isReversedOrder) {
      backLayout = secondLayout;
      frontLayout = firstLayout;
    } else {
      backLayout = firstLayout;
      frontLayout = secondLayout;
    }

    if (foldRotationListener != null) {
      foldRotationListener.onFoldRotation(rotation, isFromUser);
    }

    // When hardware acceleration is enabled view may not be invalidated and redrawn,
    // but we need it to properly draw animation
    invalidate();
  }
 private void onUpOrCancel() {
   if (!flingAnimation.isAnimating()) {
     scrollToNearestPosition();
   }
 }
 private boolean onDown() {
   isScrollDetected = false;
   animator.cancel();
   flingAnimation.stop();
   return false;
 }