Reputation: 8816
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.
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)
}
}
Upvotes: 6
Views: 2918
Reputation: 206
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)
)
}
Upvotes: 0
Reputation: 189
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
}
}
Upvotes: 3
Reputation: 119108
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.
Upvotes: 4