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