private void addNewLineAtTop(RecyclerView.Recycler recycler){
  int x=layoutStartPoint().x, bottom=getDecoratedTop(getChildAt(getMaxHeightLayoutPositionInLine(0))), y;
  int height=0;
  List<View> lineChildren=new LinkedList<>();
  int currentAdapterPosition=0;
  int endAdapterPosition=getChildAdapterPosition(0) - 1;
  Rect rect=new Rect();
  boolean newline;
  boolean firstItem=true;
  LayoutContext layoutContext=LayoutContext.fromLayoutOptions(flowLayoutOptions);
  int firstItemAdapterPosition=getChildAdapterPosition(0);
  if (cacheHelper.hasPreviousLineCached(firstItemAdapterPosition)) {
    int previousLineIndex=cacheHelper.itemLineIndex(firstItemAdapterPosition) - 1;
    Line previousLine=cacheHelper.getLine(previousLineIndex);
    int firstNewItemAdapterPosition=cacheHelper.firstItemIndex(previousLineIndex);
    for (int i=0; i < previousLine.itemCount; i++) {
      View newView=recycler.getViewForPosition(firstNewItemAdapterPosition + i);
      addView(newView,i);
      lineChildren.add(newView);
    }
    height=previousLine.maxHeight;
  }
 else {
    while (currentAdapterPosition <= endAdapterPosition) {
      View newChild=recycler.getViewForPosition(currentAdapterPosition);
      newline=calcChildLayoutRect(newChild,x,0,height,layoutContext,rect);
      cacheHelper.setItem(currentAdapterPosition,new Point(rect.width(),rect.height()));
      addView(newChild,lineChildren.size());
      if (newline && !firstItem) {
        for (        View viewToRecycle : lineChildren) {
          removeAndRecycleView(viewToRecycle,recycler);
        }
        lineChildren.clear();
        x=advanceInSameLine(layoutStartPoint().x,rect,layoutContext);
        height=rect.height();
        layoutContext.currentLineItemCount=1;
      }
 else {
        x=advanceInSameLine(x,rect,layoutContext);
        height=Math.max(height,rect.height());
        firstItem=false;
        layoutContext.currentLineItemCount++;
      }
      lineChildren.add(newChild);
      currentAdapterPosition++;
    }
  }
  x=layoutStartPoint().x;
  y=bottom - height;
  firstItem=true;
  layoutContext=LayoutContext.fromLayoutOptions(flowLayoutOptions);
  for (int i=0; i < lineChildren.size(); i++) {
    View childView=lineChildren.get(i);
    newline=calcChildLayoutRect(childView,x,y,height,layoutContext,rect);
    if (newline && firstItem) {
      int rectHeight=rect.height();
      rect.top-=rectHeight;
      rect.bottom-=rectHeight;
      firstItem=false;
    }
    layoutDecorated(childView,rect.left,rect.top,rect.right,rect.bottom);
    x=advanceInSameLine(x,rect,layoutContext);
  }
}

private void addNewLineAtTop ( RecyclerView . Recycler recycler ) { int x = layoutStartPoint ( ) . x , bottom = getDecoratedTop ( getChildAt ( getMaxHeightLayoutPositionInLine ( 0 ) ) ) , y ; int height = 0 ; List < View > lineChildren = new LinkedList < > ( ) ; int currentAdapterPosition = 0 ; int endAdapterPosition = getChildAdapterPosition ( 0 ) - 1 ; Rect rect = new Rect ( ) ; boolean newline ; boolean firstItem = true ; LayoutContext layoutContext = LayoutContext . fromLayoutOptions ( flowLayoutOptions ) ; int firstItemAdapterPosition = getChildAdapterPosition ( 0 ) ; if ( cacheHelper . hasPreviousLineCached ( firstItemAdapterPosition ) ) { int previousLineIndex = cacheHelper . itemLineIndex ( firstItemAdapterPosition ) - 1 ; Line previousLine = cacheHelper . getLine ( previousLineIndex ) ; int firstNewItemAdapterPosition = cacheHelper . firstItemIndex ( previousLineIndex ) ; for ( int i = 0 ; i < previousLine . itemCount ; i ++ ) { View newView = recycler . getViewForPosition ( firstNewItemAdapterPosition + i ) ; addView ( newView , i ) ; lineChildren . add ( newView ) ; } height = previousLine . maxHeight ; } else { while ( currentAdapterPosition <= endAdapterPosition ) { View newChild = recycler . getViewForPosition ( currentAdapterPosition ) ; newline = calcChildLayoutRect ( newChild , x , 0 , height , layoutContext , rect ) ; cacheHelper . setItem ( currentAdapterPosition , new Point ( rect . width ( ) , rect . height ( ) ) ) ; addView ( newChild , lineChildren . size ( ) ) ; if ( newline && ! firstItem ) { for ( View viewToRecycle : lineChildren ) { removeAndRecycleView ( viewToRecycle , recycler ) ; } lineChildren . clear ( ) ; x = advanceInSameLine ( layoutStartPoint ( ) . x , rect , layoutContext ) ; height = rect . height ( ) ; layoutContext . currentLineItemCount = 1 ; } else { x = advanceInSameLine ( x , rect , layoutContext ) ; height = Math . max ( height , rect . height ( ) ) ; firstItem = false ; layoutContext . currentLineItemCount ++ ; } lineChildren . add ( newChild ) ; currentAdapterPosition ++ ; } } x = layoutStartPoint ( ) . x ; y = bottom - height ; firstItem = true ; layoutContext = LayoutContext . fromLayoutOptions ( flowLayoutOptions ) ; for ( int i = 0 ; i < lineChildren . size ( ) ; i ++ ) { View childView = lineChildren . get ( i ) ; newline = calcChildLayoutRect ( childView , x , y , height , layoutContext , rect ) ; if ( newline && firstItem ) { int rectHeight = rect . height ( ) ; rect . top -= rectHeight ; rect . bottom -= rectHeight ; firstItem = false ; } layoutDecorated ( childView , rect . left , rect . top , rect . right , rect . bottom ) ; x = advanceInSameLine ( x , rect , layoutContext ) ; } }
add new line of elements at top , to keep layout , have to virtually layout from beginning . here is an example to explain why : say total width is 10 , current line is [ 5 , 2 , 1 ] , 3 numbers before current line is 7 , 2 , 6 . if you just look back , you could say previous line [ 2 , 6 ] , but there is another possibility : [ 7 , 2 ] , [ 6 ] . you don ' t know which one is correct without knowing how the line before previous one , same thing could happen to that line too , so you have to sort everything from beginning or cache the result .
