swiftuigestureswipe-gestureswiftui-tabview

Disable swipe on TabView while editing (swiftui)


I'm trying to disable the possibility to swipe a TabView in swiftui while a variable (Bool) is set to true but I must miss something very simple. I found an answer here as well as many other posts saying the same but when I run a test it doesn't prevent the swipe for me.

I have a simple test code:

struct TabViewTest: View {
@State var editing: Bool = false
var numbers:[Int] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

var body: some View {
    TabView {
        ForEach(numbers, id: \.self) { index in
            Button ("Hello, World \(index)!") {
                editing = !editing
                print("Btn \(index) changed editing to \(editing)")
            }
            .gesture(editing ? DragGesture() : nil)
        }
    }
    .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
    .indexViewStyle(PageIndexViewStyle(backgroundDisplayMode: .never))
}

}

Yet when running this I still can swipe no matter if the "editing" variable is true or false.

Here is the log from pressing the button on each Tab:

Btn 1 changed editing to true

Btn 2 changed editing to false

Btn 3 changed editing to true

Btn 4 changed editing to false

Btn 5 changed editing to true

Btn 6 changed editing to false

What am I missing? everything I find about this offer the same solution yet I'm not able to implement it ... I must miss something basic ...

I have this on the simulator with IOS 16 if this would make a difference.

Edit: it look like this is an issue others face but have not found a solution to yet, I have found a similar question here.


Solution

  • I actually found an answer in the comments of this question.

    The issue is: any view that has an "onTapGesture" will ignore ".gesture(...)".

    The solution is to use ".simulataneousGesture(...)" instead to ensure the gesture is capture and handled by both view/modifier.

    It worked perfectly in my case after changing it. The only exception is for 2 finger drag gesture.

    In my case the following code worked:

     ForEach(numbers, id: \.self) { index in
            Button ("Hello, World \(index)!") {
                editing = !editing
                print("Btn \(index) changed editing to \(editing)")
            }
            .simulataneousGesture(editing ? DragGesture() : nil)
        }