ABOUT ME

Green is Green🍏

  • SwiftUI - PinnedScrollableViews (a.k.a Sticky View)
    SwiftUI 2022. 11. 21. 17:33

    안녕하세요. 그린입니다🍏

    이번 포스팅에서는 SwiftUI에서 PinnedScrollableViews라는것에 대해 알아보겠습니다🙌

     

    이걸 알아보게 된 배경은 프로덕트의 기능을 구현하다 스크롤뷰로 감싸진 VStack에서 헤더 뷰를 구성하고 이 헤더 뷰는 스크롤을 아무리 내려도 상단에 고정시켜야 했습니다.

    이에 LazyVStack 구현 시 파라미터에 pinnedViews라는 옵션이 있었어요.

    pin하니까 역시 무언가 고정해준다는 느낌을 확 받았고, 이 타입은 PinnedScrollableViews라는것을 알게되었습니다.

    참고로 이러한 뷰를 Sticky View라고 부릅니다😊

     

    그럼 우선 PinnedScrollableViews가 무엇인지 알아보고 적용해보시죠!

     

    PinnedScrollableViews?

    iOS 14에서부터 사용가능하며 스크롤 뷰의 경계에 고정을 시켜줄 수 있는 뷰 타입 집합입니다.

    선언은 아래와 같습니다.

    struct PinnedScrollableViews

    해당 타입은 staic 변수로 기본적으로 두개의 고정 위치 선택을 위한 값을 제공해줍니다.

    sectionHeaderssectionFooters를 통해 상 / 하단 원하는 위치에 고정이 가능하죠.

    또한 조금 더 커스텀하게 UInt32의 원시값을 이용해 PinnedScrollableViews를 직접 만들 수 있습니다.

     

    요정도면 알면 충분합니다!
    그럼 바로 사용해보도록 하죠🕺🏻

     

    LazyVStack에서 PinnedScrollableViews 사용해 상단 고정 스크롤 뷰 만들기

    말보다 코드부터😀
    import SwiftUI
    
    // StickyView
    struct ContentView: View {
      let colors: [Color] = [.red, .green, .yellow, .black, .gray, .blue, .brown, .purple, .orange]
      
      var body: some View {
        VStack {
          TitleView()
          
          ScrollView(showsIndicators: false) {
            ScrollTitleView()
            
            LazyVStack(pinnedViews: .sectionHeaders) {
              Section(header: HeaderView()) {
                VStack {
                  ForEach(colors, id: \.self) { color in
                    CellItemView(color: color)
                      .padding(.horizontal, 10)
                  }
                }
              }
            }
          }
        }
      }
    }
    
    private struct TitleView: View {
      fileprivate var body: some View {
        Text("Variant Colors")
          .font(.largeTitle)
          .bold()
      }
    }
    
    private struct ScrollTitleView: View {
      fileprivate var body: some View {
        Text("ScrollView Start Point")
          .font(.largeTitle)
          .bold()
      }
    }
    
    // Sticky Header
    private struct HeaderView: View {
      fileprivate var body: some View {
        HStack {
          Spacer()
          Text("This is Header")
            .font(.title)
            .bold()
            .foregroundColor(.blue)
          Spacer()
        }
        .background(.white)
      }
    }
    
    private struct CellItemView: View {
      private var color: Color
      
      fileprivate init(color: Color) {
        self.color = color
      }
      
      fileprivate var body: some View {
        RoundedRectangle(cornerRadius: 20)
          .foregroundColor(color)
          .frame(height: 100)
      }
    }

    우선 코드가 간단해서 다른 부분은 생략하고 중요한 부분만 설명하겠습니다.

    LazyVStack 생성 시 pinnedViews 조건을 sectionHeaders로 줍니다.

    그럼 스티키하게 헤더는 상단에 고정되죠!

    그 다음 Section header에 만든 HeaderView를 담아줍니다.

    그러면 이제 정말 고정된 스크롤 헤더 뷰 완성🚀

    그 밑으로는 자유롭게 구성해주면 됩니다🙌

     

    여기서 중요한점은 Sticky Header를 만들때 background를 주지 않으면 오버레이처럼 중첩되어 나타나보입니다.

    아래와 같이 말이죠😭

     

    이런 불상사를 막기 위해 Sticky Header를 만들때 background의 색상을 white로 주면 충분해집니다.

    아마도 PinnedScrollableViews를 위해 만들어지는 Header의 백그라운드는 clear해서 그런것 같아요.

    그럼 이제 돌려보죠!

     

    챠란~~ 원하는 결과를 얻었습니다. (+1)

     

    마무리

    Sticky 구현을 처음 해봤는데 아주 유용하고 요긴하게 두루두루 휘뚜루마뚜루 잘 쓸것 같습니다👍

    위 예시 코드는 제 깃헙 레포에 있으니 필요하다면 참고해주세요😀

    https://github.com/GREENOVER/playground/tree/main/PinnedScrollableViews

     

    GitHub - GREENOVER/playground: 학습을 하며 간단한 예제들을 만들어 보는 작고 소중한 놀이터

    학습을 하며 간단한 예제들을 만들어 보는 작고 소중한 놀이터. Contribute to GREENOVER/playground development by creating an account on GitHub.

    github.com

     

    [참고 자료]

    https://developer.apple.com/documentation/swiftui/pinnedscrollableviews

     

    Apple Developer Documentation

     

    developer.apple.com

Designed by Tistory.