9

I have a TabView in SwiftUI in the PageViewTabStyle so i can swipe from page to page. I'd like to have a setting that "locks" the current view in place, so the user cannot swipe. Googling and reading docs isn't turning up anything obvious for me, so I was hoping the gurus on SO could help me out.

In short, my code looks like

TabView {
   ForEach(0..<5) { idx in
      Text("Cell: \(idx)")
   }
}
.tabViewStyle(PageTabViewStyle())

I have found the disabled property, but then it appears that all tap events are ignored on the entire view - I just want to prevent the user from switching tabs (or, in this particular case, swiping or pressing the page dots to switch pages). I've tried the solution from here where the gesture property is set to nil, but that doesn't appear to actually stop the swipe gesture from changing the page (the indexDisplayMode bit was nice, though!)

Any help is greatly appreciated! Thanks!

koen
  • 4,902
  • 6
  • 42
  • 80
Hoopes
  • 3,381
  • 4
  • 38
  • 54
  • See below - the above `gesture` solution works! However, when there is a subview with eg `onTapGesture`, the subview still intercepts the swipe to change page. I'd like to have subviews that allow touch interaction :) – Hoopes Dec 31 '20 at 19:41
  • What do you mean by subview? In a ZStack? For the code as-is, the `Text` elements don't have any subviews so you'd need to add the blocking gesture to other superviews as well – Pranav Kasetti Jan 06 '21 at 04:22

2 Answers2

12

The solution from mentioned reference works, just the swipe is blocked not by gesture(nil), but by gesture(DragGesture()). And view should be full-tab-content-view-wide, like

    TabView {
      ForEach(0..<5) { idx in
        Text("Cell: \(idx)")
                .frame(maxWidth: .infinity, maxHeight: .infinity)
                .contentShape(Rectangle())
                .gesture(DragGesture())      // this blocks swipe
      }
    }
    .tabViewStyle(PageTabViewStyle())

Tested with Xcode 12.1 / iOS 14.1

* and, of course, it can be made conditional as in https://stackoverflow.com/a/63170431/12299030

backup

Asperi
  • 173,274
  • 14
  • 284
  • 455
  • I see - If i have a subview with an `onTapGesture` property, that subview still allows swipe-to-change-pages. ``` GeometryReader { geom in TabView { ForEach(0..<5) { idx in HStack { Text("Cell: \(idx)") .onTapGesture { print ("TAP!") } // !!! .border(Color.green) } .frame(maxWidth: .infinity, maxHeight: .infinity) .contentShape(Rectangle()) .gesture(DragGesture()) // this blocks swipe } } .tabViewStyle(PageTabViewStyle()) } ``` – Hoopes Dec 31 '20 at 19:39
  • ugh, sorry for the formatting there, I'm not sure how to best reply with a chunk of code in comments. The point was, the subview with the `onTapGesture` still swipes to change the page - what's the best (if any) way to disable _that_ ? Thanks! – Hoopes Dec 31 '20 at 19:40
  • haven't tested this, but does it work if you change `.gesture(DragGesture())` to `.simulataneousGesture(DragGesture())`? – Pranav Kasetti Jan 06 '21 at 04:13
  • If either of you want to make an answer with simultaneousGesture, I can accept it. Does that allocate the bounty? I'm not sure how that works... – Hoopes Jan 07 '21 at 15:45
  • This doesn't seem to reliably disable two-finger swipe gestures for me. – nylki Aug 31 '21 at 17:00
3

To block all the swipe gestures in a TabView you have to use .simultaneousGesture(DragGesture()) that blocks all the swipe gestures in the subviews as well

TabView {
          ForEach(0..<5) { idx in
            Text("Cell: \(idx)")
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
                    .contentShape(Rectangle())
                    .simultaneousGesture(DragGesture())
          }
        }
        .tabViewStyle(PageTabViewStyle())
Mohammed Shakeer
  • 1,377
  • 13
  • 22