private boolean isFirstItemVisible() {
    final Adapter adapter = mRefreshableView.getAdapter();

    if (null == adapter || adapter.isEmpty()) {
      if (DEBUG) {
        Log.d(LOG_TAG, "isFirstItemVisible. Empty View.");
      }
      return true;

    } else {

      /**
       * This check should really just be: mRefreshableView.getFirstVisiblePosition() == 0, but
       * PtRListView internally use a HeaderView which messes the positions up. For now we'll just
       * add one to account for it and rely on the inner condition which checks getTop().
       */
      if (mRefreshableView.getFirstVisiblePosition() <= 1) {
        final View firstVisibleChild = mRefreshableView.getChildAt(0);
        if (firstVisibleChild != null) {
          return firstVisibleChild.getTop() >= mRefreshableView.getTop();
        }
      }
    }

    return false;
  }
  private boolean isLastItemVisible() {
    final Adapter adapter = mRefreshableView.getAdapter();

    if (null == adapter || adapter.isEmpty()) {
      if (DEBUG) {
        Log.d(LOG_TAG, "isLastItemVisible. Empty View.");
      }
      return true;
    } else {
      final int lastItemPosition = mRefreshableView.getCount() - 1;
      final int lastVisiblePosition = mRefreshableView.getLastVisiblePosition();

      if (DEBUG) {
        Log.d(
            LOG_TAG,
            "isLastItemVisible. Last Item Position: "
                + lastItemPosition
                + " Last Visible Pos: "
                + lastVisiblePosition);
      }

      /**
       * This check should really just be: lastVisiblePosition == lastItemPosition, but PtRListView
       * internally uses a FooterView which messes the positions up. For me we'll just subtract one
       * to account for it and rely on the inner condition which checks getBottom().
       */
      if (lastVisiblePosition >= lastItemPosition - 1) {
        final int childIndex = lastVisiblePosition - mRefreshableView.getFirstVisiblePosition();
        final View lastVisibleChild = mRefreshableView.getChildAt(childIndex);
        if (lastVisibleChild != null) {
          return lastVisibleChild.getBottom() <= mRefreshableView.getBottom();
        }
      }
    }

    return false;
  }
  public void onScroll(
      final AbsListView view,
      final int firstVisibleItem,
      final int visibleItemCount,
      final int totalItemCount) {

    if (DEBUG) {
      Log.d(
          LOG_TAG,
          "First Visible: "
              + firstVisibleItem
              + ". Visible Count: "
              + visibleItemCount
              + ". Total Items:"
              + totalItemCount);
    }

    /**
     * Set whether the Last Item is Visible. lastVisibleItemIndex is a zero-based index, so we minus
     * one totalItemCount to check
     */
    if (null != mOnLastItemVisibleListener) {
      mLastItemVisible =
          (totalItemCount > 0) && (firstVisibleItem + visibleItemCount >= totalItemCount - 1);
    }

    // If we're showing the indicator, check positions...
    if (getShowIndicatorInternal()) {
      updateIndicatorViewsVisibility();
    }

    // Finally call OnScrollListener if we have one
    if (null != mOnScrollListener) {
      mOnScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
    }
  }