관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - SwiftUI] Sticky Header 구현 방법 (Sticky 헤더) 본문

iOS 응용 (SwiftUI)

[iOS - SwiftUI] Sticky Header 구현 방법 (Sticky 헤더)

jake-kim 2024. 11. 19. 01:37

Sticky 헤더

Sticky 헤더 구현 아이디어

  • LazyVStack의 pinnedViews 파라미터에 [.sectionHeaders]를 넣을 수 있는데 이 값을 사용하면 sticky header 구현이 매우 용이
LazyVStack(pinnedViews: [.sectionHeaders])
  • 위 옵션을 주고 Section에 뷰를 넣으면 그 뷰가 sticky로 자동으로 동작됨
ScrollView {
    LazyVStack(pinnedViews: [.sectionHeaders]) {
        
        // 상단 콘텐츠
        VStack {
            Text("Top Content")
                .font(.largeTitle)
                .padding()
                .background(Color.green)
                .cornerRadius(10)
        }
        .padding()
        
        // Sticky Header가 포함된 섹션
        Section(header: MyStickyHeader()) {
        }
   }
}

구현하기

  • NavigationView, ScrollView 준비
struct ContentView: View {
    var body: some View {
        NavigationView {
            ScrollView {
                // TODO
            }
            .navigationTitle("My List")
        }
    }
}
  • ScrollView에 LazyVStack(pinnedViews:_)을 넣고 sticky header 위에 표출될 뷰 

LazyVStack(pinnedViews: [.sectionHeaders]) {
    // 상단 콘텐츠
    VStack {
        Text("Top Content")
            .font(.largeTitle)
            .padding()
            .background(Color.green)
            .cornerRadius(10)
    }
    .padding()
}
  • Sticky Header 구현하고 이것을 Section(header:)에 주입
struct MyStickyHeader: View {
    var body: some View {
        HStack {
            Text("Sticky Header")
                .font(.largeTitle)
                .bold()
                .padding()
                .frame(maxWidth: .infinity)
                .background(Color.red)
                .cornerRadius(10)
                .shadow(radius: 10)
                .foregroundColor(.white)
        }
        .frame(height: 80)
        .padding(.horizontal)
        .background(Color.red)
    }
}




LazyVStack(pinnedViews: [.sectionHeaders]) {
    // Sticky Header가 포함된 섹션
    Section(header: MyStickyHeader()) {
        // TODO 하단 콘텐츠
        
    }
}
  • 하단 컨텐츠까지 구현하면 완성
Section(header: MyStickyHeader()) {
    // 하단 콘텐츠
    ForEach(0..<50) { index in
        Text("Item \(index)")
            .padding()
            .background(Color.blue.opacity(0.3))
            .cornerRadius(10)
            .padding(.horizontal)
    }
}

Sticky 헤더


* 전체 코드

import SwiftUI

struct ContentView: View {
    var body: some View {
        NavigationView {
            ScrollView {
                LazyVStack(pinnedViews: [.sectionHeaders]) {
                    
                    // 상단 콘텐츠
                    VStack {
                        Text("Top Content")
                            .font(.largeTitle)
                            .padding()
                            .background(Color.green)
                            .cornerRadius(10)
                    }
                    .padding()
                    
                    // Sticky Header가 포함된 섹션
                    Section(header: MyStickyHeader()) {
                        // 하단 콘텐츠
                        ForEach(0..<50) { index in
                            Text("Item \(index)")
                                .padding()
                                .background(Color.blue.opacity(0.3))
                                .cornerRadius(10)
                                .padding(.horizontal)
                        }
                    }
                }
            }
            .navigationTitle("My List")
        }
    }
}

struct MyStickyHeader: View {
    var body: some View {
        HStack {
            Text("Sticky Header")
                .font(.largeTitle)
                .bold()
                .padding()
                .frame(maxWidth: .infinity)
                .background(Color.red)
                .cornerRadius(10)
                .shadow(radius: 10)
                .foregroundColor(.white)
        }
        .frame(height: 80)
        .padding(.horizontal)
        .background(Color.red) // Background를 추가하여 scroll 영역과 일치 시킴
    }
}
Comments