Skip to content

Instantly share code, notes, and snippets.

@chriseidhof
Last active February 13, 2020 09:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chriseidhof/0503901d3d481e77a981ab3702b8ddd9 to your computer and use it in GitHub Desktop.
Save chriseidhof/0503901d3d481e77a981ab3702b8ddd9 to your computer and use it in GitHub Desktop.
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