article

Thursday, February 24, 2022

SwiftUI ScrollView Sticky Header

SwiftUI ScrollView Sticky Header

ContentView.swift
 
//
//  ContentView.swift
//  SwiftUIProject
//
//  Created by Cairocoders
//

import SwiftUI

struct ContentView: View {
    
    var body: some View {
        ScrollView(.vertical, showsIndicators: false) {
            StickyHeader {
                StickyHeader {
                    Image("3")
                        .resizable()
                        .aspectRatio(contentMode: .fill)
                }
            }
            
            HStack(alignment: .center) {
                VStack {
                    Text("Taylor")
                        .padding()
                        .font(.title)
                    Text("Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit..")
                        .padding()
                    Image("1")
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                        .padding(.all, 20)
                    
                    Text("Caitelyn")
                        .padding()
                        .font(.title)
                    
                    Image("2")
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                        .padding(.all, 20)
                
                }.padding(10)
            }
            .frame(maxWidth: .infinity, alignment: .center)
            .background(Color.white)
            .modifier(CardModifier())
            .padding(.all, 10)
            
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

struct StickyHeader<Content: View>: View {

    var minHeight: CGFloat
    var content: Content
    
    init(minHeight: CGFloat = 200, @ViewBuilder content: () -> Content) {
        self.minHeight = minHeight
        self.content = content()
    }
    
    var body: some View {
        GeometryReader { geo in
            if(geo.frame(in: .global).minY <= 0) {
                content
                    .frame(width: geo.size.width, height: geo.size.height, alignment: .center)
            } else {
                content
                    .offset(y: -geo.frame(in: .global).minY)
                    .frame(width: geo.size.width, height: geo.size.height + geo.frame(in: .global).minY)
            }
        }.frame(minHeight: minHeight)
    }
}

struct CardModifier: ViewModifier {
    func body(content: Content) -> some View {
        content
            .cornerRadius(20)
            .shadow(color: Color.black.opacity(0.2), radius: 20, x: 0, y: 0)
    }
    
}

Related Post