@Override
    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {

        if (adapter == null || adapter.getItemCount() == 0) {
            return;
        }

        if (scrollTargetAdapterPosition >= 0) {
            firstViewAdapterPosition = scrollTargetAdapterPosition;
            firstViewTop = 0;
            scrollTargetAdapterPosition = RecyclerView.NO_POSITION; // we're done here
        } else if (pendingSavedState != null && pendingSavedState.isValid()) {
            firstViewAdapterPosition = pendingSavedState.firstViewAdapterPosition;
            firstViewTop = pendingSavedState.firstViewTop;
            pendingSavedState = null; // we're done with saved state now
        } else {
            updateFirstAdapterPosition();
        }

        int top = firstViewTop;

        // RESET
        headerViews.clear();
        headerPositionsBySection.clear();
        detachAndScrapAttachedViews(recycler);

        int height;
        int left = getPaddingLeft();
        int right = getWidth() - getPaddingRight();
        int parentBottom = getHeight() - getPaddingBottom();
        int totalVendedHeight = 0;

        // If we emptied the view with a notify, we may overshoot and fail to draw
        if (firstViewAdapterPosition >= state.getItemCount()) {
            firstViewAdapterPosition = state.getItemCount() - 1;
        }

        // walk through adapter starting at firstViewAdapterPosition stacking each vended item
        for (int adapterPosition = firstViewAdapterPosition; adapterPosition < state.getItemCount(); adapterPosition++) {

            View v = recycler.getViewForPosition(adapterPosition);
            addView(v);
            measureChildWithMargins(v, 0, 0);

            int itemViewType = getViewBaseType(v);
            if (itemViewType == SectioningAdapter.TYPE_HEADER) {
                headerViews.add(v);

                // use the header's height
                height = getDecoratedMeasuredHeight(v);
                layoutDecorated(v, left, top, right, top + height);

                // we need to vend the ghost header and position/size it same as the actual header
                adapterPosition++;
                View ghostHeader = recycler.getViewForPosition(adapterPosition);
                addView(ghostHeader);
                layoutDecorated(ghostHeader, left, top, right, top + height);

            } else if (itemViewType == SectioningAdapter.TYPE_GHOST_HEADER) {

                // we need to back up and get the header for this ghostHeader
                View headerView = recycler.getViewForPosition(adapterPosition - 1);
                headerViews.add(headerView);
                addView(headerView);
                measureChildWithMargins(headerView, 0, 0);
                height = getDecoratedMeasuredHeight(headerView);

                layoutDecorated(headerView, left, top, right, top + height);
                layoutDecorated(v, left, top, right, top + height);

            } else {
                height = getDecoratedMeasuredHeight(v);
                layoutDecorated(v, left, top, right, top + height);
            }

            top += height;
            totalVendedHeight += height;

            // if the item we just laid out falls off the bottom of the view, we're done
            if (v.getBottom() >= parentBottom) {
                break;
            }
        }

        // determine if scrolling is necessary to fill viewport
        int innerHeight = getHeight() - (getPaddingTop() + getPaddingBottom());
        if (totalVendedHeight < innerHeight) {
            // note: we're passing null for RecyclerView.State - this is "safe"
            // only because we don't use it for scrolling negative dy
            scrollVerticallyBy(totalVendedHeight - innerHeight, recycler, null);
        } else {
            // no scroll correction necessary, so position headers
            updateHeaderPositions(recycler);
        }
    }
Assign callback object to be notified when a header view position changes between states of the HeaderPosition enum

@param headerPositionChangedCallback the callback
@see HeaderPosition
android/modules/module_common/src/main/java/github/tornaco/android/thanos/widget/section/StickyHeaderLayoutManager.java