79391888

Date: 2025-01-27 19:04:52
Score: 0.5
Natty:
Report link

You can achieve this layout using .contentRelativeFrame and without a GeometryReader. This was inspired by the approach shown in this video by Stewart Lynch.

import SwiftUI

struct OverviewTiles: View {
    
    //Constants
    let ratio: Double = 0.666
    let spacing: CGFloat = 16
    
    //Body
    var body: some View {
        
        ScrollView {
            VStack(spacing: spacing) {
                
                //Row 1
                HStack(spacing: spacing) {
                    Color.blue
                        .aspectRatio(1, contentMode: .fit)
                        .containerRelativeFrame(.horizontal) { dimension, _ in
                            largeWidth(dimension)
                        }
                        .cellText("Upcoming Blue", size: .title)
                        
                    VStack(spacing: spacing) {
                        Color.cyan
                            .aspectRatio(1, contentMode: .fit)
                            .cellText("Blue 1")
                        Color.cyan
                            .aspectRatio(1, contentMode: .fit)
                            .cellText("Blue 2")
                    }
                    .containerRelativeFrame(.horizontal, alignment: .trailing) { dimension, _ in
                        secondaryWidth(dimension)
                    }
                }
                
                //Row 2
                HStack(spacing: spacing) {
                    Color.green
                        .aspectRatio(2, contentMode: .fit)
                        .containerRelativeFrame(.horizontal) { dimension, _ in
                            largeWidth(dimension)
                        }
                        .cellText("Upcoming Green", size: .title2)
                    
                    Color.green
                        .aspectRatio(1, contentMode: .fit)
                        .containerRelativeFrame(.horizontal) { dimension, _ in
                            secondaryWidth(dimension)
                        }
                        .cellText("Green 1")
                }
                
                //Row 3
                Color.orange
                    .aspectRatio(2.5, contentMode: .fit)
                    .cellText("Upcoming Orange", size: .title)
            }
        }
    }
    
    private func largeWidth(_ dimension: CGFloat) -> CGFloat {
        return dimension * ratio
    }
    
    private func secondaryWidth(_ dimension: CGFloat) -> CGFloat {
        return (dimension * (1 - ratio)) - spacing
    }
}

extension View {
    
    //Modifier function that overlays bottom aligned text with a background
    func cellText(_ text: String, size: Font = .body, alignment: Alignment = .bottom) -> some View {
        self
            .overlay(alignment: .bottom) {
                Text(text)
                    .italic()
                    .padding(.vertical, 10)
                    .frame(maxWidth: .infinity, alignment: .center)
                    .background(.black.opacity(0.5))
                    .foregroundStyle(.white)
                    .font(size)
                    .fontDesign(.serif)
            }
    }
}

#Preview {
    OverviewTiles()
}

enter image description here

Reasons:
  • Blacklisted phrase (1): this video
  • Probably link only (1):
  • Long answer (-1):
  • Has code block (-0.5):
Posted by: Andrei G.