SwiftUILazyContainer

2.0.0

Lazy rendering and layouts in SwiftUI ScrollView
ciaranrobrien/SwiftUILazyContainer

What's New

v2.0.0

2024-05-01T20:57:19Z

Reworked implementation, added masonry layouts, added aspect ratio subview sizing, updated API, updated documentation.

SwiftUI LazyContainer

Lazy rendering and layouts in a SwiftUI ScrollView.

For existing SwiftUI layouts, consider SwiftUIOnVisible instead to get callbacks when subviews become visible in a ScrollView.

Get Started

Use lazyContainer to configure the scroll view for lazy rendering.

Use AltLazyVStack as a replacement for VStack or LazyVStack to only render its content when visible in the scroll view.

ScrollView {
    AltLazyVStack(data, contentHeight: 200) { element in
        /// Lazy content
    }
}
.lazyContainer()

Use LazyVMasonry to arrange subviews in a vertical masonry with lazy rendering.

ScrollView {
    LazyVMasonry(data, columns: 2, contentHeights: [.fraction(1/4), .fraction(1/5)]) { element in
        /// Lazy content
    }
}
.lazyContainer(renderingPadding: 16, rendersInSafeAreaEdges: .all)

Advanced Usage

Use template and lazySubviewTemplate to provide hidden template views for sizing lazy subviews.

ScrollView {
    VStack {
        AltLazyVStack(data, contentHeight: .template) { element in
            /// Lazy content
        }
    }
}
.lazyContainer {
    VStack {
        Text(verbatim: "Placeholder")
            .font(.headline)
        
        Text(verbatim: "Placeholder")
            .font(.subheadline)
    }
    .padding()
    .lineLimit(1)
    .lazySubviewTemplate()
}

Use the contentHeight closure to resolve subview heights for each element. Combine LazySubviewSize values with + or sum to dynamically build subview heights.

ScrollView {
    LazyVMasonry(data, columns: .adaptive(minSize: 140), spacing: 8) { element in
        /// Lazy content
    } contentHeight: { element in
        let imageHeight = LazySubviewSize.aspect(element.imageSize.width / element.imageSize.height)
        let titleHeight = LazySubviewSize.template(id: element.subtitle == nil ? 1 : 2)
        return imageHeight + titleHeight
    }
}
.lazyContainer {
    Text(verbatim: "Title Placeholder")
        .font(.headline)
        .padding()
        .lineLimit(1)
        .lazySubviewTemplate(id: 1)
    
    VStack {
        Text(verbatim: "Title Placeholder")
            .font(.headline)
        
        Text(verbatim: "Subtitle Placeholder")
            .font(.subheadline)
    }
    .padding()
    .lineLimit(1)
    .lazySubviewTemplate(id: 2)
}

See Examples for more.

Requirements

  • iOS 13.0+, macOS 10.15+, tvOS 13.0+, watchOS 6.0+, visionOS 1.0+
  • Xcode 15.0+

Installation

Contact

@ciaranrobrien on Twitter.

Description

  • Swift Tools 5.10.0
View More Packages from this Author

Dependencies

  • None
Last updated: Fri Dec 13 2024 09:05:05 GMT-1000 (Hawaii-Aleutian Standard Time)