docs: private void layoutForPredictiveAnimationsExpose(RecyclerView.Recycler recycler,
                                                       RecyclerView.State state, int startOffset, int endOffset) {
          // If there are scrap children that we did not layout, we need to find where they did go
          // and layout them accordingly so that animations can work as expected.
          // This case may happen if new views are added or an existing view expands and pushes
          // another view out of bounds.
          if (!state.willRunPredictiveAnimations() || getChildCount() == 0 || state.isPreLayout()
                  || !supportsPredictiveItemAnimations()) {
              return;
          }
  
          // to make the logic simpler, we calculate the size of children and call fill.
          int scrapExtraStart = 0, scrapExtraEnd = 0;
          final List<RecyclerView.ViewHolder> scrapList = recycler.getScrapList();
          final int scrapSize = scrapList.size();
          final int firstChildPos = getPosition(getChildAt(0));
          for (int i = 0; i < scrapSize; i++) {
              RecyclerView.ViewHolder scrap = scrapList.get(i);
              final int position = scrap.getPosition();
              final int direction = position < firstChildPos != mShouldReverseLayoutExpose
                      ? LayoutState.LAYOUT_START : LayoutState.LAYOUT_END;
              if (direction == LayoutState.LAYOUT_START) {
                  scrapExtraStart += mOrientationHelper.getDecoratedMeasurement(scrap.itemView);
              } else {
                  scrapExtraEnd += mOrientationHelper.getDecoratedMeasurement(scrap.itemView);
              }
          }
  
          if (DEBUG) {
              Log.d(TAG, "for unused scrap, decided to add " + scrapExtraStart
                      + " towards start and " + scrapExtraEnd + " towards end");
          }
          mLayoutState.mScrapList = scrapList;
          if (scrapExtraStart > 0) {
              View anchor = getChildClosestToStartExpose();
              updateLayoutStateToFillStartExpose(getPosition(anchor), startOffset);
              mLayoutState.mExtra = scrapExtraStart;
              mLayoutState.mAvailable = 0;
              mLayoutState.mCurrentPosition += mShouldReverseLayoutExpose ? 1 : -1;
              mLayoutState.mOnRefresLayout = true;
              fill(recycler, mLayoutState, state, false);
          }
  
          if (scrapExtraEnd > 0) {
              View anchor = getChildClosestToEndExpose();
              updateLayoutStateToFillEndExpose(getPosition(anchor), endOffset);
              mLayoutState.mExtra = scrapExtraEnd;
              mLayoutState.mAvailable = 0;
              mLayoutState.mCurrentPosition += mShouldReverseLayoutExpose ? -1 : 1;
              mLayoutState.mOnRefresLayout = true;
              fill(recycler, mLayoutState, state, false);
          }
          mLayoutState.mScrapList = null;
      }