extension View { /// Overlays another view on top of this view. /// /// - Parameter alignment: The alignment that the modifier uses to position /// the overlay relative to the underlying content. /// - Parameter content: The view to overlay this view with. public func overlay( alignment: Alignment = .center, @ViewBuilder content: () -> some View ) -> some View { OverlayModifier(content: self, overlay: content(), alignment: alignment) } } struct OverlayModifier: TypeSafeView { typealias Children = TupleView2.Children var body: TupleView2 var alignment: Alignment init(content: Content, overlay: Overlay, alignment: Alignment) { body = TupleView2(content, overlay) self.alignment = alignment } func children( backend: Backend, snapshots: [ViewGraphSnapshotter.NodeSnapshot]?, environment: EnvironmentValues ) -> TupleView2.Children { body.children( backend: backend, snapshots: snapshots, environment: environment ) } func layoutableChildren( backend: Backend, children: TupleView2.Children ) -> [LayoutSystem.LayoutableChild] { [] } func asWidget( _ children: TupleView2.Children, backend: Backend ) -> Backend.Widget { body.asWidget(children, backend: backend) } func computeLayout( _ widget: Backend.Widget, children: TupleView2.Children, proposedSize: ProposedViewSize, environment: EnvironmentValues, backend: Backend ) -> ViewLayoutResult { let contentResult = children.child0.computeLayout( with: body.view0, proposedSize: proposedSize, environment: environment ) let contentSize = contentResult.size let overlayResult = children.child1.computeLayout( with: body.view1, proposedSize: ProposedViewSize(contentSize), environment: environment ) let overlaySize = overlayResult.size let size = ViewSize( max(contentSize.width, overlaySize.width), max(contentSize.height, overlaySize.height) ) return ViewLayoutResult( size: size, childResults: [contentResult, overlayResult] ) } func commit( _ widget: Backend.Widget, children: TupleView2.Children, layout: ViewLayoutResult, environment: EnvironmentValues, backend: Backend ) { let frameSize = layout.size.vector let contentSize = children.child0.commit().size.vector let overlaySize = children.child1.commit().size.vector let contentPosition = alignment.position(ofChild: contentSize, in: frameSize) let overlayPosition = alignment.position(ofChild: overlaySize, in: frameSize) backend.setPosition(ofChildAt: 0, in: widget, to: contentPosition) backend.setPosition(ofChildAt: 1, in: widget, to: overlayPosition) backend.setSize(of: widget, to: frameSize) } }