SwiftUI 中的垂直分页

发布于 2025-01-10 04:09:10 字数 2404 浏览 0 评论 0原文

我正在通过 TabView 创建一个垂直分页视图,如下 this

一切都很完美,除了奇怪的右边距,如下图所示。

这是我使用的代码。如果有人能指出根本原因,我将不胜感激。

输入图像描述这里

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)
    }


}

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)
    }


}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

寒尘 2025-01-17 04:09:10

iOS 17 中的水平/垂直分页

iOS 17 开始,您不需要旋转选项卡视图,您可以通过在 ScrollView 上应用以下修饰符来启用分页行为

.scrollTargetBehavior(.paging)

因此,ScrollView 内的任何内容(例如堆栈内的简单 ForEach)都将根据需要进行分页。这适用于水平滚动视图和垂直滚动视图。

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.

吾家有女初长成 2025-01-17 04:09:10

有 iOS17 修饰符 .scrollTargetBehavior(.paging),对于旧版本,此 hack 应该有效:

import SwiftUIIntrospect

GeometryReader { proxy in
    ScrollView {
        LazyVStack(spacing: 0) {
            ForEach([Color.red, Color.green, Color.blue], id: \.self) { color in
                color.frame(proxy.size)
            }
        }
    }
    .introspect(.scrollView, on: .iOS(.v15, .v16, .v17)) { sv in
        sv.isPagingEnabled = true
    }
}

There is iOS17 modifier .scrollTargetBehavior(.paging), for older versions this hack should work:

import SwiftUIIntrospect

GeometryReader { proxy in
    ScrollView {
        LazyVStack(spacing: 0) {
            ForEach([Color.red, Color.green, Color.blue], id: \.self) { color in
                color.frame(proxy.size)
            }
        }
    }
    .introspect(.scrollView, on: .iOS(.v15, .v16, .v17)) { sv in
        sv.isPagingEnabled = true
    }
}
梦里寻她 2025-01-17 04:09:10

尝试在 TabView 内的 content 视图上添加 scaledToFill() 修饰符。该修改器会缩放视图以填充其父视图。我发现当 content 视图是 AsyncImageImage 视图时它可以工作,并且它应该适用于任何单个视图。然而,对于水平的 TabView 来说,它也有同样的问题,即屏幕右边缘的奇怪边距。

示例代码如下:

  TabView {
                    content.scaledToFill()
                    .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)
                )
}

Try adding the scaledToFill() modifier on the content view within the TabView. That modifier scales the view to fill its parent. I've found that it works when the content view is an AsyncImage or Image view and it should work with any single views. However, with a horizontal TabView and it had the same issue with the strange margin on the right edge of the screen.

Example code below:

  TabView {
                    content.scaledToFill()
                    .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)
                )
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文