You can track the progress of the swipe with the geometry reader and handle accordingly. This example below gives the solution to your problem. It shows you the correct selected tap page in the Text()
... You can then do a .onChange(of:)
where you can handle any changes when the selected tap changes.
struct ContentView: View {
enum SwipeDirection {
case left
case right
case none
}
@State var items = [0, 1, 2]
@State var selection: Int = 0
@State var swipeDirection: SwipeDirection = .none
var body: some View {
VStack() {
TabView(selection: $selection) {
ForEach($items.indices, id: \.self) { item in
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundColor(.accentColor)
Text("Hello, world! \(item)")
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.tag(item)
.background(
GeometryReader { proxy in
Color.blue.preference(key: CustomPreferenceKey.self, value: proxy.frame(in: .global).minX)
}
)
}
}.tabViewStyle(.page)
Text("\(selection)")
}
.onPreferenceChange(CustomPreferenceKey.self) {
if $0 >= (UIScreen.main.bounds.width - 20) {
swipeDirection = .left
} else if $0 <= -(UIScreen.main.bounds.width - 20) {
swipeDirection = .right
}
switch swipeDirection {
case .right:
if $0 == 0 {
selection += 1
}
case .left:
if $0 == 0 {
selection -= 1
}
case .none: break
}
swipeDirection = .none
}
.onChange(of: selection) { newValue in
// this is where you do your thing!!
}
}
}
struct CustomPreferenceKey: PreferenceKey {
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {}
static var defaultValue: CGFloat = 0
}