iOS 16 - Create wrapping layout with Layout protocol

Updated
Jun 7, 2022 10:36 PM
Created
Jun 7, 2022 10:31 PM
Tags
SwiftUI.framework
Attributes

On iOS 16, SwiftUI provides Layout protocol, which let us make our own fully customized layout.

I’ve tried to make a layout that wraps according to their contents. it’s very very beginning.

image

struct Wrap: Layout {

  func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) -> CGSize {

    print(proposal, subviews)
    Log.debug(proposal, subviews)

    return .init(width: 200, height: 200)
  }

  func placeSubviews(
    in bounds: CGRect,
    proposal: ProposedViewSize,
    subviews: Subviews,
    cache: inout ()
  ) {
    
    var offsetX: Double = 0
    var offsetY: Double = 0
        
    for (_, view) in subviews.enumerated() {
      
      let size = view.sizeThatFits(.init(width: bounds.width, height: bounds.height))
      
      if (size.width + offsetX) > bounds.width {
        offsetX = 0
        offsetY += 30
      }
      
      let rectInBounds = CGRect(
        origin: CGPoint.init(
          x: offsetX,
          y: offsetY
        ),
        size: size
      )
      
      let point = CGPoint(
        x: rectInBounds.minX + bounds.minX,
        y: rectInBounds.minY + bounds.minY
      )
      
      view.place(
        at: point,
        proposal: .init(width: bounds.width, height: bounds.height)
      )
      
      offsetX += rectInBounds.width + 2
    }
    
  }

}