private void updateHeader(int headerPosition) {

    // check if there is a new header should be sticky
    if (mHeaderPosition == null || mHeaderPosition != headerPosition) {
      mHeaderPosition = headerPosition;
      final long headerId = mAdapter.getHeaderId(headerPosition);
      if (mHeaderId == null || mHeaderId != headerId) {
        mHeaderId = headerId;
        final View header = mAdapter.getHeaderView(mHeaderPosition, mHeader, this);
        if (mHeader != header) {
          if (header == null) {
            throw new NullPointerException("header may not be null");
          }
          swapHeader(header);
        }
        ensureHeaderHasCorrectLayoutParams(mHeader);
        measureHeader(mHeader);
        if (mOnStickyHeaderChangedListener != null) {
          mOnStickyHeaderChangedListener.onStickyHeaderChanged(
              this, mHeader, headerPosition, mHeaderId);
        }
        // Reset mHeaderOffset to null ensuring
        // that it will be set on the header and
        // not skipped for performance reasons.
        mHeaderOffset = null;
      }
    }

    int headerOffset = 0;

    // Calculate new header offset
    // Skip looking at the first view. it never matters because it always
    // results in a headerOffset = 0
    int headerBottom = mHeader.getMeasuredHeight() + stickyHeaderTop();
    for (int i = 0; i < mList.getChildCount(); i++) {
      final View child = mList.getChildAt(i);
      final boolean doesChildHaveHeader =
          child instanceof WrapperView && ((WrapperView) child).hasHeader();
      final boolean isChildFooter = mList.containsFooterView(child);
      if (child.getTop() >= stickyHeaderTop() && (doesChildHaveHeader || isChildFooter)) {
        headerOffset = Math.min(child.getTop() - headerBottom, 0);
        break;
      }
    }

    setHeaderOffet(headerOffset);

    if (!mIsDrawingListUnderStickyHeader) {
      mList.setTopClippingLength(mHeader.getMeasuredHeight() + mHeaderOffset);
    }

    updateHeaderVisibilities();
  }