swiftuipagingtabview

Vertical Paging in SwiftUI


I'm creating a vertical paging view via TabView following this

Everything is perfect except the strange right margin as highlighted in pic below.

Here is the code I use. Appreciate it if anyone could point out the root cause.

enter image description here

import SwiftUI

fileprivate struct VCompatibleTabView<Content: View>: View {
    let proxy: GeometryProxy
    let content: Content
    
    init(proxy: GeometryProxy, @ViewBuilder content: () -> Content) {
        self.proxy = proxy
        self.content = content()
    }
    
    var body: some View {
        if #available(iOS 15.0, *) {
            // Credit to Gary Tokmen for this bit of Geometry Reader code: https://blog.prototypr.io/how-to-vertical-paging-in-swiftui-f0e4afa739ba
            TabView {
                content
                .rotationEffect(.degrees(-90)) // Rotate content
                .frame(
                    width: proxy.size.width,
                    height: proxy.size.height
                )
            }
            .frame(
                width: proxy.size.height, // Height & width swap
                height: proxy.size.width
            )
            .rotationEffect(.degrees(90), anchor: .topLeading) // Rotate TabView
            .offset(x: proxy.size.width) // Offset back into screens bounds
            .tabViewStyle(
                PageTabViewStyle(indexDisplayMode: .never)
            )
        } else {
            ScrollView(.vertical, showsIndicators: false) {
                LazyVStack(spacing: 0) {
                    content
                }
            }
            .frame(
                width: proxy.size.width,
                height: proxy.size.height)        }
    }
}

struct BBYouView: View {

    var body: some View {
        ZStack {
            GeometryReader { proxy in
                VCompatibleTabView(proxy: proxy) {
                    ForEach(0..<3, id: \.self) { item in
                        Rectangle().fill(Color.pink)
                        .frame(
                            width: proxy.size.width,
                            height: proxy.size.height
                        )
                    }
                }
            }
        }
        .background(Color.yellow)
    }


}

Solution

  • Horizontal/Vertical paging in iOS 17

    From iOS 17, you don't need to do the hack of rotating the tab view and you can enable the paging behavior by applying the following modifier on the ScrollView:

    .scrollTargetBehavior(.paging)
    

    So anything inside the ScrollView like a simple ForEach inside a stack would be paging as desired. This works for both horizontal and vertical scrollviews.