휘리릭(?) 넘어가는 것이 아니라 슥슥(?) 넘어가는 ScrollView (feat. scrollTargetBehavior)

SteadySlower·2024년 1월 21일
0

SwiftUI

목록 보기
59/64

휘리릭 넘어가지 말고 슥슥 넘어가게 부탁드려요.

회사 디자이너 분께 일반적인 스크롤 뷰를 구현해서 드렸더니 저런 피드백이 돌아왔다. 휘리릭은 뭐고 슥슥은 무엇인가? 그 사람의 설명에 의하면 휘리릭은 관성을 받아서 컨텐츠들이 물 흐르듯이 넘어가는 것이고 슥슥은 인스타 사진이 넘어가듯이 컨텐츠들이 하나하나 단위로 넘어가는 것이라 한다.

즉 페이지 뷰처럼 넘어가는 스크롤 뷰를 원하는 것이다. 하지만 페이지 뷰로 할 수는 없었는데 양쪽에 다음 컨텐츠의 일부가 보여야 했기 때문이다.

휘리릭

내가 처음에 구현한 뷰는 아래와 같은 지극히 평범한 ScrollView이다.

import SwiftUI

struct HomeView: View {
    
    let colors: [Color] = [.red, .blue, .green, .pink, .black]
    
    var body: some View {
        ScrollView(.horizontal, showsIndicators: false) {
            HStack {
                ForEach(colors, id: \.self) { color in
                    color
                        .frame(width: 300, height: 200)
                }
            }
        }
        .padding(.horizontal, 30)
    }
    
}

#Preview {
    HomeView()
}

한번에 스크롤 만으로도 관성으로 인해 색깔들이 휘리리리리리리릭 넘어가는 것을 볼 수 있다.

.scrollTargetBehavior(.paging)

ScrollView를 그대로 사용해서 디자이너의 요구사항을 충족시켜줘 보자. iOS 17부터는 .scrollTargetBehavior라는 기능이 생겼는데 이 상황에 딱 맞는 기능이다. behavior의 종류 중에서 .paging을 선택하면 아래와 같이 된다

import SwiftUI

struct HomeView: View {
    
    let colors: [Color] = [.red, .blue, .green, .pink, .black]
    
    var body: some View {
        ScrollView(.horizontal, showsIndicators: false) {
            HStack {
                ForEach(colors, id: \.self) { color in
                    color
                        .frame(width: 300, height: 200)
                }
            }
        }
        .padding(.horizontal, 30)
        .scrollTargetBehavior(.paging)
    }
    
}

#Preview {
    HomeView()
}

페이지 뷰와 비슷하게 약간의 swipe로는 색이 넘어가지 않고 강하게 swipe를 하더라도 관성의 작용 없이 하나의 색깔만 넘길 수 있다. 아주 편리한 기능이고 나도 개인적으로 기다려왔던 기능인데

최대 단점이 iOS 17부터 사용할 수 있다는 것이다. PM은 iOS 16.0 → iOS 16.4도 못하게 하는 중이다.

야매로 해보자

자 그러면 그냥 안된다고 할 것인가? 최근에 서점에서 “오늘도 개발자가 안된다고 했다”라는 책을 발견했다. 뭔가 꼼수를 부려서 해보자. 꼼수의 방법은 아래와 같다. 앱 내에 존재하는 모든 UIScrollView가 paging이 되도록 수정하는 것이다.

위와 동일하게 동작”하기는” 한다. 하지만 이 방법을 권장하지 않는 것이 iOS 버전에 따라서 될 때도 있고 안 될때도 있다. 심지어 한 화면에 존재 하는 모든 스크롤뷰가 paging이 되버린다는 치명적인 단점이 있다.

import SwiftUI

struct HomeView: View {
    
    let colors: [Color] = [.red, .blue, .green, .pink, .black]
    
    var body: some View {
        ScrollView(.horizontal, showsIndicators: false) {
            HStack {
                ForEach(colors, id: \.self) { color in
                    color
                        .frame(width: 300, height: 200)
                }
            }
        }
        .padding(.horizontal, 30)
        .onAppear {
            UIScrollView.appearance().isPagingEnabled = true
        }
        .onDisappear {
            UIScrollView.appearance().isPagingEnabled = false
        }
    }
    
}

#Preview {
    HomeView()
}

마치며…

우리 회사는 대부분의 경우 하나의 기획과 디자인을 가지고 iOS 개발자와 안드로이드 개발자가 짝을 이뤄서 같은 앱을 만드는데 위와 같은 페이징 되는 스크롤의 경우 안드로이드는 아주 쉽게 구현할 수 있다고 한다.

하지만 나는 예전에 일일히 offset을 구해서 만들었는데 그건 굉장히 버거운 작업이었던 것으로 기억한다.

이제 드디어 SwiftUI에 이런 것이 생겼는데 iOS 17부터라니… 시간이 흐르기를 기다리는 수 밖에는 없는 것인가?

참고로 scrollTargetBehavior에는 paging 말고도 좀 더 커스터마이징이 가능한 기능을 탑재하고 있다. 다음에 포스팅을 통해서 다뤄보겠다.

profile
백과사전 보다 항해일지(혹은 표류일지)를 지향합니다.

0개의 댓글