private void updateOrClearHeader(int firstVisiblePosition) { final int adapterCount = mAdapter == null ? 0 : mAdapter.getCount(); if (adapterCount == 0 || !mAreHeadersSticky) { return; } final int headerViewCount = mList.getHeaderViewsCount(); int headerPosition = firstVisiblePosition - headerViewCount; if (mList.getChildCount() > 0) { View firstItem = mList.getChildAt(0); if (firstItem.getBottom() < stickyHeaderTop()) { headerPosition++; } } // It is not a mistake to call getFirstVisiblePosition() here. // Most of the time getFixedFirstVisibleItem() should be called // but that does not work great together with getChildAt() final boolean doesListHaveChildren = mList.getChildCount() != 0; final boolean isFirstViewBelowTop = doesListHaveChildren && mList.getFirstVisiblePosition() == 0 && mList.getChildAt(0).getTop() >= stickyHeaderTop(); final boolean isHeaderPositionOutsideAdapterRange = headerPosition > adapterCount - 1 || headerPosition < 0; if (!doesListHaveChildren || isHeaderPositionOutsideAdapterRange || isFirstViewBelowTop) { clearHeader(); return; } updateHeader(headerPosition); }
// hides the headers in the list under the sticky header. // Makes sure the other ones are showing private void updateHeaderVisibilities() { int top; if (mHeader != null) { top = mHeader.getMeasuredHeight() + (mHeaderOffset != null ? mHeaderOffset : 0); } else { top = mClippingToPadding ? mPaddingTop : 0; } int childCount = mList.getChildCount(); for (int i = 0; i < childCount; i++) { View child = mList.getChildAt(i); if (child instanceof WrapperView) { WrapperView wrapperViewChild = (WrapperView) child; if (wrapperViewChild.hasHeader()) { View childHeader = wrapperViewChild.mHeader; if (wrapperViewChild.getTop() < top) { if (childHeader.getVisibility() != View.INVISIBLE) { childHeader.setVisibility(View.INVISIBLE); } } else { if (childHeader.getVisibility() != View.VISIBLE) { childHeader.setVisibility(View.VISIBLE); } } } } } }
// hides the headers in the list under the sticky header. // Makes sure the other ones are showing private void updateHeaderVisibilities() { int top = stickyHeaderTop(); int childCount = mList.getChildCount(); for (int i = 0; i < childCount; i++) { // ensure child is a wrapper view View child = mList.getChildAt(i); if (!(child instanceof WrapperView)) { continue; } // ensure wrapper view child has a header WrapperView wrapperViewChild = (WrapperView) child; if (!wrapperViewChild.hasHeader()) { continue; } // update header views visibility View childHeader = wrapperViewChild.mHeader; if (wrapperViewChild.getTop() < top) { if (childHeader.getVisibility() != View.INVISIBLE) { childHeader.setVisibility(View.INVISIBLE); } } else { if (childHeader.getVisibility() != View.VISIBLE) { childHeader.setVisibility(View.VISIBLE); } } } }
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(); }
public View getListChildAt(int index) { return mList.getChildAt(index); }