/**
   * Like {@link View#scrollBy}, but scroll smoothly instead of immediately.
   *
   * @param x the number of pixels to scroll by on the X axis
   * @param y the number of pixels to scroll by on the Y axis
   * @param velocity the velocity associated with a fling, if applicable. (0 otherwise)
   */
  void smoothScrollTo(int x, int y, int velocity) {
    if (getChildCount() == 0) {
      // Nothing to do.
      setScrollingCacheEnabled(false);
      return;
    }
    int sx = getScrollX();
    int sy = getScrollY();
    int dx = x - sx;
    int dy = y - sy;
    if (dx == 0 && dy == 0) {
      completeScroll();
      if (isMenuOpen()) {
        if (mOpenedListener != null) mOpenedListener.onOpened();
      } else {
        if (mClosedListener != null) mClosedListener.onClosed();
      }
      return;
    }

    setScrollingCacheEnabled(true);
    mScrolling = true;

    final int width = getBehindWidth();
    final int halfWidth = width / 2;
    final float distanceRatio = Math.min(1f, 1.0f * Math.abs(dx) / width);
    final float distance = halfWidth + halfWidth * distanceInfluenceForSnapDuration(distanceRatio);

    int duration = 0;
    velocity = Math.abs(velocity);
    if (velocity > 0) {
      duration = 4 * Math.round(1000 * Math.abs(distance / velocity));
    } else {
      final float pageDelta = (float) Math.abs(dx) / width;
      duration = (int) ((pageDelta + 1) * 100);
      duration = MAX_SETTLE_DURATION;
    }
    duration = Math.min(duration, MAX_SETTLE_DURATION);

    mScroller.startScroll(sx, sy, dx, dy, duration);
    invalidate();
  }
 private void completeScroll() {
   boolean needPopulate = mScrolling;
   if (needPopulate) {
     // Done with scroll, no longer want to cache view drawing.
     setScrollingCacheEnabled(false);
     mScroller.abortAnimation();
     int oldX = getScrollX();
     int oldY = getScrollY();
     int x = mScroller.getCurrX();
     int y = mScroller.getCurrY();
     if (oldX != x || oldY != y) {
       scrollTo(x, y);
     }
     if (isMenuOpen()) {
       if (mOpenedListener != null) mOpenedListener.onOpened();
     } else {
       if (mClosedListener != null) mClosedListener.onClosed();
     }
   }
   mScrolling = false;
 }