@Override
  public void onPageScrollStateChanged(int scrollState) {
    if (hardwaredDisabled) {
      hardwaredDisabled = false;
      enableHWAcceleration(nativeView);
    }
    mPager.requestDisallowInterceptTouchEvent(scrollState != ViewPager.SCROLL_STATE_IDLE);

    if (scrollState == ViewPager.SCROLL_STATE_DRAGGING) {
      updateCurrentPageDuringScroll = true;
      ((ScrollableViewProxy) proxy).fireScrollStart(mCurIndex, mViews.get(mCurIndex));
    } else if ((scrollState == ViewPager.SCROLL_STATE_IDLE) && isValidScroll) {
      int oldIndex = mCurIndex;
      {
        updateCurrentPageDuringScroll = false;
        ((ScrollableViewProxy) proxy).fireScrollEnd(mCurIndex, mViews.get(mCurIndex));
      }
      if (mCurIndex >= 0) {
        //				if (oldIndex >=0 && oldIndex != mCurIndex && oldIndex < mViews.size()) {
        //					// Don't know what these focused and unfocused
        //					// events are good for, but they were in our previous
        //					// scrollable implementation.
        //					// cf.
        // https://github.com/appcelerator/titanium_mobile/blob/20335d8603e2708b59a18bafbb91b7292278de8e/android/modules/ui/src/ti/modules/titanium/ui/widget/TiScrollableView.java#L260
        //					TiEventHelper.fireFocused(mViews.get(oldIndex));
        //				}
        //
        //				TiEventHelper.fireUnfocused(mViews.get(mCurIndex));
        if (oldIndex >= 0) {
          // oldIndex will be -1 if the view has just
          // been created and is setting currentPage
          // to something other than 0. In that case we
          // don't want a `scrollend` to fire.
          ((ScrollableViewProxy) proxy).fireScrollEnd(mCurIndex, mViews.get(mCurIndex));
        }

        if (shouldShowPager()) {
          showPager();
        }
      }

      // If we don't use this state variable to check if it's a valid
      // scroll, this event will fire when the view is first created
      // because on creation, the scroll state is initialized to
      // `idle` and this handler is called.
      isValidScroll = false;
    } else if (scrollState == ViewPager.SCROLL_STATE_SETTLING) {
      updateCurrentPageDuringScroll = false;
      ((ScrollableViewProxy) proxy).fireDragEnd(mCurIndex, mViews.get(mCurIndex));

      // Note that we just fired a `dragend` so the `onPageSelected`
      // handler below doesn't fire a `scrollend`.  Read below comment.
      justFiredDragEnd = true;
    }
  }
 private void setCurrentPageIndex(int newPage, boolean animated) {
   if (newPage == mCurIndex) return;
   mCurIndex = newPage;
   proxy.setProperty(TiC.PROPERTY_CURRENT_PAGE, mCurIndex);
   updateCacheSize();
   ((ScrollableViewProxy) proxy).firePageChange(mCurIndex, mViews.get(mCurIndex));
 }
  public void showPager() {
    View v = null;
    v = mContainer.findViewById(PAGE_LEFT);
    if (v != null) {
      v.setVisibility(mCurIndex > 0 ? View.VISIBLE : View.INVISIBLE);
    }

    v = mContainer.findViewById(PAGE_RIGHT);
    if (v != null) {
      v.setVisibility(mCurIndex < (mViews.size() - 1) ? View.VISIBLE : View.INVISIBLE);
    }

    mPagingControl.setVisibility(View.VISIBLE);
    ((ScrollableViewProxy) proxy).setPagerTimeout();
  }
  @Override
  public void onPageScrolled(
      int positionRoundedDown, float positionOffset, int positionOffsetPixels) {
    if (hardwaredDisabled) {
      hardwaredDisabled = false;
      enableHWAcceleration(nativeView);
    }
    isValidScroll = true;
    int oldIndex = mCurIndex;

    // When we touch and drag the view and hold it inbetween the second
    // and third sub-view, this function will have been called with values
    // similar to:
    //		positionRoundedDown:	1
    //		positionOffset:			 0.5
    // ie, the first parameter is always rounded down; the second parameter
    // is always just an offset between the current and next view, it does
    // not take into account the current view.

    // If we add positionRoundedDown to positionOffset, positionOffset will
    // have the 'correct' value; ie, will be a natural number when we're on
    // one particular view, something.5 when inbetween views, etc.
    float positionFloat = positionOffset + positionRoundedDown;

    // `positionFloat` can now be used to calculate the correct value for
    // the current index. We add 0.5 so that positionFloat will be rounded
    // half up; ie, if it has a value of 1.5, it will be rounded up to 2; if
    // it has a value of 1.4, it will be rounded down to 1.
    int index = Math.min(Math.max((int) Math.floor(positionFloat + 0.5), 0), mViews.size() - 1);
    if (updateCurrentPageDuringScroll) {
      setCurrentPageIndex(index, true);
    }
    ((ScrollableViewProxy) proxy).fireScroll(mCurIndex, positionFloat, mViews.get(mCurIndex));

    // Note that we didn't just fire a `dragend`.  See the above comment
    // in `onPageSelected`.
    justFiredDragEnd = false;

    // Force the container to redraw on scrolling.
    // Without this the outer pages render initially and then stay static
    nativeView.invalidate();
  }
  @Override
  public void onPageSelected(int page) {

    setCurrentPageIndex(page, true);
    updateCurrentPageDuringScroll = false;
    // If we didn't just fire a `dragend` event then this is the case
    // where a user drags the view and settles it on a different view.
    // Since the OS settling logic is never run, the
    // `onPageScrollStateChanged` handler is never run, and therefore
    // we forgot to inform the Javascripters that the user just scrolled
    // their thing.

    if (!justFiredDragEnd && mCurIndex != -1 && mCurIndex < mViews.size()) {
      ((ScrollableViewProxy) proxy).fireScrollEnd(mCurIndex, mViews.get(mCurIndex));

      if (shouldShowPager()) {
        showPager();
      }
    }
  }