26

I have set up a TabView in my application, so that I can swipe horizontally between multiple pages, but I also have an unwanted vertical scroll that may appear, with a bounce effect so. How can I disable this vertical scroll?

My code:


struct ContentView: View {
  @State private var currentTabIndex: Double = 0

  var body: some View {
    VStack {
      TabView(selection: $currentTabIndex) {
        Text("Text n°1")
          .tag(0)
        
        Text("Text n°2")
          .tag(1)
      }
      .border(Color.black)
      .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
    }
  }
}
Guillaume
  • 1,500
  • 3
  • 24
  • 33
  • 2
    Looks like a bug or something that can not be changed at the moment. Offtopic: but you have to use Double in your tag aswell, if you specify `currentTabIndex` as Double. – davidev Sep 27 '20 at 18:18

3 Answers3

16

I had this same problem. It's not an exact solution, but you can turn off bouncing on scrollviews (which is used within a TabView). And as long as the items within the TabView are not larger than the TabView frame, it should act as if you disabled vertical scrolling.

I would call it either .onAppear or in your init function:

.onAppear(perform: {
   UIScrollView.appearance().bounces = false
 })

Note: this disables the bouncing on ALL scrollviews across your app... So you may want to re-enable it .onDisappear.

nicksarno
  • 3,850
  • 1
  • 13
  • 33
  • Thanks for this! In my case the contents are definitely smaller than the TabView frame, so you do have any insight into why it scrolls in the first place? – Duc Oct 02 '20 at 14:02
  • I also wish it didn't haha. It seems like each tab is based on a ScrollView, which is probably done so that in situations where the content IS larger than the TabView frame, the user can scroll on it (just my guess, idrk). – nicksarno Oct 02 '20 at 22:15
  • Is there any other solution? I would like to keep the bouncing function, but only deactivate the vertically scroll function for the tabview – Erik Mar 18 '21 at 18:02
  • @Erik I haven't found any other native solution, however, I've played around with this [SwiftUI Pager project](https://github.com/fermoya/SwiftUIPager) (not affiliated) instead of the paging tab view, and it works pretty well. – nicksarno Mar 19 '21 at 14:29
  • Not working for me so i did like this `UIScrollView.appearance().isScrollEnabled = false` – Abhishek Thapliyal May 26 '22 at 09:55
8

Still an issue with Xcode 12.4.

I managed to workaround that by wrapping the TabView within a ScrollView and using the alwaysBounceVertical property set to false, as follow:

ScrollView(.horizontal) {
    TabView {
        ///your content goes here
    }
    .tabViewStyle(PageTabViewStyle())
}
.onAppear(perform: {
    UIScrollView.appearance().alwaysBounceVertical = false
})
.onDisappear(perform: {
    UIScrollView.appearance().alwaysBounceVertical = true
})
valvoline
  • 7,737
  • 3
  • 47
  • 52
  • With `UIScrollView.appearance().bounces = false` and `UIScrollView.appearance().bounces = true` it worked for me. – herve Sep 21 '21 at 19:10
1

I actually came across this because I saw this effect in a tutorial but couldn’t replicate it on iOS 15.2. However, I managed to replicate it on iOS 14.4 on another simulator side by side. So I guess this behaviour is disabled or fundamentally changed in the newer iOS.

Demonstration

DogLoaf
  • 11
  • 2
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Steven-Carrot Jul 14 '22 at 20:39