protected void setRefreshingInternal(boolean doScroll) {
    mState = REFRESHING;

    if (mMode.canPullDown()) {
      mHeaderLayout.refreshing();
    }
    if (mMode.canPullUp()) {
      mFooterLayout.refreshing();
    }

    if (doScroll) {
      if (mShowViewWhileRefreshing) {
        smoothScrollTo(mCurrentMode == Mode.PULL_DOWN_TO_REFRESH ? -mHeaderHeight : mHeaderHeight);
      } else {
        smoothScrollTo(0);
      }
    }
  }
  /**
   * Called when the UI has been to be updated to be in the {@link
   * com.handmark.pulltorefresh.library.PullToRefreshBase.State#RESET} state.
   */
  protected void onReset() {
    mIsBeingDragged = false;
    mLayoutVisibilityChangesEnabled = true;

    // Always reset both layouts, just in case...
    mHeaderLayout.reset();
    mFooterLayout.reset();

    smoothScrollTo(0);
  }
  protected void resetHeader() {
    mState = PULL_TO_REFRESH;
    mIsBeingDragged = false;

    if (mMode.canPullDown()) {
      mHeaderLayout.reset();
    }
    if (mMode.canPullUp()) {
      mFooterLayout.reset();
    }

    smoothScrollTo(0);
  }
  private final void smoothScrollToAndBack(int y) {
    smoothScrollTo(
        y,
        SMOOTH_SCROLL_DURATION_MS,
        0,
        new OnSmoothScrollFinishedListener() {

          @Override
          public void onSmoothScrollFinished() {
            smoothScrollTo(0, SMOOTH_SCROLL_DURATION_MS, DEMO_SCROLL_INTERVAL, null);
          }
        });
  }
  /**
   * Called when the UI has been to be updated to be in the {@link
   * com.handmark.pulltorefresh.library.PullToRefreshBase.State#REFRESHING} or {@link
   * com.handmark.pulltorefresh.library.PullToRefreshBase.State#MANUAL_REFRESHING} state.
   *
   * @param doScroll - Whether the UI should scroll for this event.
   */
  protected void onRefreshing(final boolean doScroll) {
    if (mMode.showHeaderLoadingLayout()) {
      mHeaderLayout.refreshing();
    }
    if (mMode.showFooterLoadingLayout()) {
      mFooterLayout.refreshing();
    }

    if (doScroll) {
      if (mShowViewWhileRefreshing) {

        // Call Refresh Listener when the Scroll has finished
        OnSmoothScrollFinishedListener listener =
            new OnSmoothScrollFinishedListener() {
              @Override
              public void onSmoothScrollFinished() {
                callRefreshListener();
              }
            };

        switch (mCurrentMode) {
          case MANUAL_REFRESH_ONLY:
          case PULL_FROM_END:
            smoothScrollTo(getFooterSize(), listener);
            break;
          default:
          case PULL_FROM_START:
            smoothScrollTo(-getHeaderSize(), listener);
            break;
        }
      } else {
        smoothScrollTo(0);
      }
    } else {
      // We're not scrolling, so just call Refresh Listener now
      callRefreshListener();
    }
  }
 /**
  * Smooth Scroll to Y position using the default duration of {@value #SMOOTH_SCROLL_DURATION_MS}
  * ms.
  *
  * @param y - Y position to scroll to
  */
 protected final void smoothScrollTo(int y) {
   smoothScrollTo(y, SMOOTH_SCROLL_DURATION_MS);
 }
  @Override
  public final boolean onTouchEvent(MotionEvent event) {

    if (!isPullToRefreshEnabled()) {
      return false;
    }

    // If we're refreshing, and the flag is set. Eat the event
    if (mDisableScrollingWhileRefreshing && isRefreshing()) {
      return true;
    }

    if (event.getAction() == MotionEvent.ACTION_DOWN && event.getEdgeFlags() != 0) {
      return false;
    }

    switch (event.getAction()) {
      case MotionEvent.ACTION_MOVE:
        {
          if (mIsBeingDragged) {
            mLastMotionY = event.getY();
            pullEvent();
            return true;
          }
          break;
        }

      case MotionEvent.ACTION_DOWN:
        {
          if (isReadyForPull()) {
            mLastMotionY = mInitialMotionY = event.getY();
            return true;
          }
          break;
        }

      case MotionEvent.ACTION_CANCEL:
      case MotionEvent.ACTION_UP:
        {
          if (mIsBeingDragged) {
            mIsBeingDragged = false;

            if (mState == RELEASE_TO_REFRESH) {
              if (null != mOnRefreshListener) {
                setRefreshingInternal(true);
                mOnRefreshListener.onRefresh(this);
                return true;

              } else if (null != mOnRefreshListener2) {
                setRefreshingInternal(true);
                if (mCurrentMode == Mode.PULL_DOWN_TO_REFRESH) {
                  mOnRefreshListener2.onPullDownToRefresh(this);
                } else if (mCurrentMode == Mode.PULL_UP_TO_REFRESH) {
                  mOnRefreshListener2.onPullUpToRefresh(this);
                }
                return true;
              } else {
                // If we don't have a listener, just reset
                resetHeader();
                return true;
              }
            }

            smoothScrollTo(0);
            return true;
          }
          break;
        }
    }

    return false;
  }
 /**
  * Smooth Scroll to position using the default duration of {@value #SMOOTH_SCROLL_DURATION_MS} ms.
  *
  * @param scrollValue - Position to scroll to
  */
 protected final void smoothScrollTo(int scrollValue) {
   smoothScrollTo(scrollValue, getPullToRefreshScrollDuration());
 }
  @Override
  public final boolean onTouchEvent(MotionEvent event) {

    if (!isPullToRefreshEnabled()) {
      return false;
    }

    // If we're refreshing, and the flag is set. Eat the event
    if (!mScrollingWhileRefreshingEnabled && isRefreshing()) {
      return true;
    }

    if (event.getAction() == MotionEvent.ACTION_DOWN && event.getEdgeFlags() != 0) {
      return false;
    }

    switch (event.getAction()) {
      case MotionEvent.ACTION_MOVE:
        {
          if (mIsBeingDragged) {
            mLastMotionY = event.getY();
            mLastMotionX = event.getX();
            pullEvent();
            return true;
          }
          break;
        }

      case MotionEvent.ACTION_DOWN:
        {
          if (isReadyForPull()) {
            mLastMotionY = mInitialMotionY = event.getY();
            mLastMotionX = mInitialMotionX = event.getX();
            return true;
          }
          break;
        }

      case MotionEvent.ACTION_CANCEL:
      case MotionEvent.ACTION_UP:
        {
          if (mIsBeingDragged) {
            mIsBeingDragged = false;

            if (mState == State.RELEASE_TO_REFRESH
                && (null != mOnRefreshListener || null != mOnRefreshListener2)) {
              setState(State.REFRESHING, true);
              return true;
            }

            // If we're already refreshing, just scroll back to the top
            if (isRefreshing()) {
              smoothScrollTo(0);
              return true;
            }

            // If we haven't returned by here, then we're not in a state
            // to pull, so just reset
            setState(State.RESET);

            return true;
          }
          break;
        }
    }

    return false;
  }
 /**
  * Smooth Scroll to position using the specific duration
  *
  * @param scrollValue - Position to scroll to
  * @param duration - Duration of animation in milliseconds
  */
 private final void smoothScrollTo(int scrollValue, long duration) {
   smoothScrollTo(scrollValue, duration, 0, null);
 }
 /**
  * Smooth Scroll to position using the default duration of {@value #SMOOTH_SCROLL_DURATION_MS} ms.
  *
  * @param scrollValue - Position to scroll to
  * @param listener - Listener for scroll
  */
 protected final void smoothScrollTo(int scrollValue, OnSmoothScrollFinishedListener listener) {
   smoothScrollTo(scrollValue, getPullToRefreshScrollDuration(), 0, listener);
 }