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(); }