Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Flexible Frames
import SwiftUI
extension View {
func assert(size: CGSize) -> some View {
self.overlay(GeometryReader { proxy in
Group {
if size == proxy.size {
Color.clear
} else {
Color.red.opacity(0.5)
}
}
})
}
}
struct ContentView: View {
var body: some View {
Text("Hello, World!")
}
}
/// When you propose a nil size through `fixedSize()`, the default size for a `Shape` is (10, 10).
struct Sample1: View {
var body: some View {
Rectangle()
.assert(size: CGSize(width: 10, height: 10))
.fixedSize()
}
}
/// When you propose a nil size through `fixedSize()`, the ideal size is used.
struct Sample2: View {
var body: some View {
Rectangle()
.assert(size: CGSize(width: 50, height: 50))
.frame(idealWidth: 50, idealHeight: 50)
.assert(size: CGSize(width: 50, height: 50))
.fixedSize()
}
}
/// When the ideal size is used, and the child is smaller than the ideal size, the ideal size is reported back.
struct Sample3: View {
var body: some View {
Rectangle()
.frame(width: 50, height: 50)
.frame(idealWidth: 75, idealHeight: 75)
.fixedSize()
.assert(size: CGSize(width: 75, height: 75))
.border(Color.red)
}
}
/// When the ideal size is used, and the child is larger than the ideal size, the ideal size is reported back.
struct Sample4: View {
var body: some View {
Rectangle()
.frame(width: 75, height: 75)
.frame(idealWidth: 50, idealHeight: 50)
.fixedSize()
.assert(size: CGSize(width: 50, height: 50))
.border(Color.red)
}
}
/// When there is a nil proposal but no ideal width, the minimum width is used.
struct Sample5: View {
var body: some View {
Rectangle().fill(Color.green)
.frame(minWidth: 50, idealHeight: 50)
.fixedSize()
.assert(size: CGSize(width: 50, height: 50))
.border(Color.red)
}
}
/// The reported child's size is clamped to the minimum and maximum dimensions.
struct Sample6: View {
var body: some View {
Rectangle().fill(Color.green)
.frame(width: 35, height: 70)
.frame(minWidth: 50, maxHeight: 50)
.assert(size: CGSize(width: 50, height: 50))
.border(Color.red)
}
}
/// When we use `fixedSize()` on a `Stack`, the `Stack` proposes nil dimension to its children. In the example above, the blue rectangle reports it's 50 points wide, and the green rectangle reports it's 10 points wide (`Shape`'s default ideal size). The resulting child size from the first pass (60 by 50 points) is then again proposed (during the second layout pass) to the children. This time around, the horizontal width is divided equally (and the ideal width is ignored because a non-nil size is proposed).
struct Sample7: View {
var body: some View {
HStack {
Rectangle()
.fill(Color.blue)
.frame(idealWidth: 50, idealHeight: 50)
.assert(size: CGSize(width: 60/2, height: 50))
Rectangle()
.fill(Color.green)
.assert(size: CGSize(width: 60/2, height: 50))
}.fixedSize()
}
}
/// Things like padding "work as expected": they don't do anything when the nil size is proposed, but add to the computed size of the child.
struct Sample8: View {
var body: some View {
Rectangle()
.fill(Color.red)
.frame(idealWidth: 50, idealHeight: 50)
.padding(10)
.fixedSize()
.assert(size: CGSize(width: 70, height: 70))
.border(Color.green)
}
}
/// When you propose a nil size through `fixedSize()`, the default size for a `Path` is (10, 10).
struct Sample9: View {
var body: some View {
Path { p in
p.addRect(.init(x: 0, y: 0, width: 200, height: 100))
}
.assert(size: CGSize(width: 10, height: 10))
.border(Color.red)
.fixedSize()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
Group {
Sample1()
.previewDisplayName("Sample 1")
Sample2()
.previewDisplayName("Sample 2")
Sample3()
.previewDisplayName("Sample 3")
Sample4()
.previewDisplayName("Sample 4")
Sample5()
.previewDisplayName("Sample 5")
Sample6()
.previewDisplayName("Sample 6")
Sample7()
.previewDisplayName("Sample 7")
Sample8()
.previewDisplayName("Sample 8")
Sample9()
.previewDisplayName("Sample 9")
}.previewLayout(.fixed(width: 200, height: 200))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.