How to make container view in SwiftUI

Issue #450

Following the signatures of ScrollView and Group, we can create our own container

1
2
3
4
5
6
public struct ScrollView<Content> : View where Content : View {

/// The content of the scroll view.
public var content: Content

}
1
2
3
4
5
6
7
8
9
10
extension Group : View where Content : View {

/// The type of view representing the body of this view.
///
/// When you create a custom view, Swift infers this type from your
/// implementation of the required `body` property.
public typealias Body = Never

@inlinable public init(@ViewBuilder content: () -> Content)
}

For example, below is a FullWidth that encapsulate a child element and make it full width

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import SwiftUI

struct FullWidth<Content>: View where Content: View {
let content: Content

var body: some View {
GeometryReader { geometry in
self.content
.frame(width: geometry.size.width, height: geometry.size.width, alignment: .center)
.padding(.bottom, geometry.size.width)
}
}

@inlinable public init(@ViewBuilder content: () -> Content) {
self.content = content()
}
}

struct FullWidth_Previews: PreviewProvider {
static var previews: some View {
FullWidth {
Text("")
}
}
}

One problem with GeometryReader is that the size of the children can’t affect the size of its container. We need to apply Geometry at the root level

1
2
3
4
5
6
7
8
9
10
11
12
var body: some View {
GeometryReader { geometry in
ScrollView {
VStack(alignment: .leading, spacing: 8) {
Text("title")
RemoteImage(url: self.item.url)
.frame(width: geometry.size.width, height: geometry.size.height, alignment: .center)
Text("footer")
}
}
}
}

Comments