I am building something similar to an Instagram story. But whatever I tried either tabview tag or tap gesture works. I could not make them both work together. The purpose is if I tap the left or right side of the view it will jump to another story of the same storyModel. if I scroll tabview it will jump to another storyModel.
This is the extension I have tried
struct OnTap: ViewModifier {
let response: (CGPoint) -> Void
@State private var location: CGPoint = .zero
func body(content: Content) -> some View {
content
.onTapGesture {
response(location)
}
.simultaneousGesture(
DragGesture(minimumDistance: 0)
.onEnded { location = $0.location }
)
}
}
extension View {
func onTapGesture(_ handler: @escaping (CGPoint) -> Void) -> some View {
self.modifier(OnTap(response: handler))
}
}
struct OnTapAndTagAction: ViewModifier {
let onTap: (CGPoint) -> Void
let index: Int
func body(content: Content) -> some View {
content
.overlay(
Rectangle()
.fill(Color.clear)
.onTapGesture { tapLocation in
onTap(tapLocation)
}
)
.tag(index)
}
}
extension View {
func onTapGestureAndTag(index: Int, _ handler: @escaping (CGPoint) -> Void) -> some View {
self.modifier(OnTapAndTagAction(onTap: handler, index: index))
}
}
And this is how I use it
struct StoryDetailView: View {
ZStack {
Color.storyNotchPurple
.edgesIgnoringSafeArea(.top)
TabView(selection: $selectedStoryId) {
Color.storyNotchPurple.edgesIgnoringSafeArea(.top)
ForEach(storyModelArray.indices, id: \.self) { index in
GeometryReader {...}
.onTapGestureAndTag(index: index) { tapLocation in
if tapLocation.x < screenWidth / 2 {
if currentStoryIndex > 1 {
currentStoryIndex -= 1
}
} else {
if currentStoryIndex < progressCount {
currentStoryIndex += 1
}
}
}
}
}
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
.edgesIgnoringSafeArea(.top)
}
instead of tap gesture I have used buttons and z index
HStack {
Button(action: {
if currentStoryIndex > 1 {
currentStoryIndex -= 1
}
}) {
Color.clear
.contentShape(Rectangle())
.frame(width: screenWidth / 2, height: g.size.height - 100)
}
.buttonStyle(PlainButtonStyle())
Button(action: {
if currentStoryIndex < progressCount {
currentStoryIndex += 1
}
}) {
Color.clear
.contentShape(Rectangle())
.frame(width: screenWidth / 2, height: g.size.height - 100)
}
.buttonStyle(PlainButtonStyle())
}
.zIndex(1)