public void setDisplayedViewIndex(int i) {
   if (0 <= i && i < mAdapter.getCount()) {
     onMoveOffChild(mCurrent);
     mCurrent = i;
     onMoveToChild(i);
     mResetLayout = true;
     requestLayout();
   }
 }
  @Override
  protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);

    View cv = mChildViews.get(mCurrent);
    Point cvOffset;

    if (!mResetLayout) {
      // Move to next or previous if current is sufficiently off center
      if (cv != null) {
        cvOffset = subScreenSizeOffset(cv);
        // cv.getRight() may be out of date with the current scale
        // so add left to the measured width for the correct position
        if (cv.getLeft() + cv.getMeasuredWidth() + cvOffset.x + GAP / 2 + mXScroll < getWidth() / 2
            && mCurrent + 1 < mAdapter.getCount()) {
          postUnsettle(cv);
          // post to invoke test for end of animation
          // where we must set hq area for the new current view
          post(this);

          onMoveOffChild(mCurrent);
          mCurrent++;
          onMoveToChild(mCurrent);
        }

        if (cv.getLeft() - cvOffset.x - GAP / 2 + mXScroll >= getWidth() / 2 && mCurrent > 0) {
          postUnsettle(cv);
          // post to invoke test for end of animation
          // where we must set hq area for the new current view
          post(this);

          onMoveOffChild(mCurrent);
          mCurrent--;
          onMoveToChild(mCurrent);
        }
      }

      // Remove not needed children and hold them for reuse
      int numChildren = mChildViews.size();
      int childIndices[] = new int[numChildren];
      for (int i = 0; i < numChildren; i++) childIndices[i] = mChildViews.keyAt(i);

      for (int i = 0; i < numChildren; i++) {
        int ai = childIndices[i];
        if (ai < mCurrent - 1 || ai > mCurrent + 1) {
          View v = mChildViews.get(ai);
          onNotInUse(v);
          mViewCache.add(v);
          removeViewInLayout(v);
          mChildViews.remove(ai);
        }
      }
    } else {
      mResetLayout = false;
      mXScroll = mYScroll = 0;

      // Remove all children and hold them for reuse
      int numChildren = mChildViews.size();
      for (int i = 0; i < numChildren; i++) {
        View v = mChildViews.valueAt(i);
        onNotInUse(v);
        mViewCache.add(v);
        removeViewInLayout(v);
      }
      mChildViews.clear();
      // post to ensure generation of hq area
      post(this);
    }

    // Ensure current view is present
    int cvLeft, cvRight, cvTop, cvBottom;
    boolean notPresent = (mChildViews.get(mCurrent) == null);
    cv = getOrCreateChild(mCurrent);
    // When the view is sub-screen-size in either dimension we
    // offset it to center within the screen area, and to keep
    // the views spaced out
    cvOffset = subScreenSizeOffset(cv);
    if (notPresent) {
      // Main item not already present. Just place it top left
      cvLeft = cvOffset.x;
      cvTop = cvOffset.y;
    } else {
      // Main item already present. Adjust by scroll offsets
      cvLeft = cv.getLeft() + mXScroll;
      cvTop = cv.getTop() + mYScroll;
    }
    // Scroll values have been accounted for
    mXScroll = mYScroll = 0;
    cvRight = cvLeft + cv.getMeasuredWidth();
    cvBottom = cvTop + cv.getMeasuredHeight();

    if (!mUserInteracting && mScroller.isFinished()) {
      Point corr = getCorrection(getScrollBounds(cvLeft, cvTop, cvRight, cvBottom));
      cvRight += corr.x;
      cvLeft += corr.x;
      cvTop += corr.y;
      cvBottom += corr.y;
    } else if (cv.getMeasuredHeight() <= getHeight()) {
      // When the current view is as small as the screen in height, clamp
      // it vertically
      Point corr = getCorrection(getScrollBounds(cvLeft, cvTop, cvRight, cvBottom));
      cvTop += corr.y;
      cvBottom += corr.y;
    }

    cv.layout(cvLeft, cvTop, cvRight, cvBottom);

    if (mCurrent > 0) {
      View lv = getOrCreateChild(mCurrent - 1);
      Point leftOffset = subScreenSizeOffset(lv);
      int gap = leftOffset.x + GAP + cvOffset.x;
      lv.layout(
          cvLeft - lv.getMeasuredWidth() - gap,
          (cvBottom + cvTop - lv.getMeasuredHeight()) / 2,
          cvLeft - gap,
          (cvBottom + cvTop + lv.getMeasuredHeight()) / 2);
    }

    if (mCurrent + 1 < mAdapter.getCount()) {
      View rv = getOrCreateChild(mCurrent + 1);
      Point rightOffset = subScreenSizeOffset(rv);
      int gap = cvOffset.x + GAP + rightOffset.x;
      rv.layout(
          cvRight + gap,
          (cvBottom + cvTop - rv.getMeasuredHeight()) / 2,
          cvRight + rv.getMeasuredWidth() + gap,
          (cvBottom + cvTop + rv.getMeasuredHeight()) / 2);
    }

    invalidate();
  }