There are different ways to limit or constrain a subview within its superview in SwiftUI. ‘GeometryReader’ is one among those for relative sizing of the subviews in a view. We will see different ways of using ‘GeometryReader’ in below examples.
ContainerExample
:
- Uses basic containment with percentage-based sizing
- Child view takes up 80% of parent’s width and height
- Uses
position
to center the child view
import SwiftUI
struct ContentView: View {
var body: some View {
// Example 1: Basic containment
VStack(spacing: 20) {
ContainerExample()
}
}
}
// Example 1: Basic containment with fixed size
struct ContainerExample: View {
var body: some View {
GeometryReader { geometry in
// Parent container
RoundedRectangle(cornerRadius: 10)
.fill(.blue.opacity(0.2))
.overlay(
// Child view using parent's dimensions
RoundedRectangle(cornerRadius: 5)
.fill(.blue)
.frame(
width: geometry.size.width * 0.8,
height: geometry.size.height * 0.8
)
.position(
x: geometry.size.width / 2,
y: geometry.size.height / 2
)
)
}
.frame(height: 200)
}
}
#Preview {
ContentView()
.padding()
}
2. CenteredContentExample
:
- Shows how to center content with dynamic sizing
- Uses
min
to ensure content doesn’t exceed container - Demonstrates padding consideration in calculations
import SwiftUI
struct ContentView: View {
var body: some View {
// Example 1: Basic containment
VStack(spacing: 20) {
CenteredContentExample()
}
}
}
// Example 2: Centered content with dynamic sizing
struct CenteredContentExample: View {
var body: some View {
GeometryReader { geometry in
ZStack {
// Background
RoundedRectangle(cornerRadius: 10)
.fill(.green.opacity(0.2))
// Centered content with padding
VStack {
Text("Centered Content")
.font(.headline)
RoundedRectangle(cornerRadius: 5)
.fill(.green)
.frame(
width: min(geometry.size.width - 40, 300),
height: min(geometry.size.height - 40, 100)
)
}
}
}
.frame(height: 200)
}
}
#Preview {
ContentView()
.padding()
}
3. ResponsiveContainerExample
:
- Shows how to create a responsive grid layout
- Adapts to available space
- Uses spacing and padding considerations
import SwiftUI
struct ContentView: View {
var body: some View {
// Example 1: Basic containment
VStack(spacing: 20) {
ResponsiveContainerExample()
}
}
}
// Example 3: Responsive container that adapts to content
struct ResponsiveContainerExample: View {
var body: some View {
GeometryReader { geometry in
let availableWidth = geometry.size.width
let availableHeight = geometry.size.height
ZStack {
// Background container
RoundedRectangle(cornerRadius: 10)
.fill(.purple.opacity(0.2))
// Dynamic content grid
HStack(spacing: 10) {
ForEach(0..<3) { index in
RoundedRectangle(cornerRadius: 5)
.fill(.purple)
.frame(
width: (availableWidth - 40) / 3,
height: availableHeight * 0.6
)
}
}
.position(
x: availableWidth / 2,
y: availableHeight / 2
)
}
}
.frame(height: 200)
}
}
#Preview {
ContentView()
.padding()
}
4. ProportionalContainerExample
:
- Maintains aspect ratio of the contained view
- Uses
aspectRatio
withcontentMode: .fit
- Ensures square shape while staying within bounds
import SwiftUI
struct ContentView: View {
var body: some View {
// Example 1: Basic containment
VStack(spacing: 20) {
ProportionalContainerExample()
}
}
}
// Example 4: Proportional container with aspect ratio
struct ProportionalContainerExample: View {
var body: some View {
GeometryReader { geometry in
// Parent container
RoundedRectangle(cornerRadius: 10)
.fill(.orange.opacity(0.2))
.overlay(
// Child view maintaining aspect ratio
RoundedRectangle(cornerRadius: 5)
.fill(.orange)
.aspectRatio(1.0, contentMode: .fit)
.frame(
width: min(geometry.size.width, geometry.size.height) * 0.8
)
.position(
x: geometry.size.width / 2,
y: geometry.size.height / 2
)
)
}
.frame(height: 200)
}
}
#Preview {
ContentView()
.padding()
}
#Preview {
ContentView()
.padding()
}
Key tips for using GeometryReader:
a. Always account for padding in your calculations
b. Use position
for precise positioning
c. Consider using min
and max
for boundaries
d. Remember that GeometryReader takes up all available space
e. Use local variables to make calculations clearer
Thanks for reading!