27

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))
    }
  }
}
1
  • 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. Commented Sep 27, 2020 at 18:18

5 Answers 5

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.

Sign up to request clarification or add additional context in comments.

5 Comments

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?
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).
Is there any other solution? I would like to keep the bouncing function, but only deactivate the vertically scroll function for the tabview
@Erik I haven't found any other native solution, however, I've played around with this SwiftUI Pager project (not affiliated) instead of the paging tab view, and it works pretty well.
Not working for me so i did like this UIScrollView.appearance().isScrollEnabled = false
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
})

1 Comment

With UIScrollView.appearance().bounces = false and UIScrollView.appearance().bounces = true it worked for me.
2

iOS 18+, Project build Xcode 16 only.

Had the same issue with but with TabView horizontal scrolling(the solution is not axis-specific).

Put on TabView highPriorityGesture DragGesture:

.highPriorityGesture(DragGesture())

And if you want to control scroll availability you can go with:

.highPriorityGesture(DragGesture(), isEnabled: isTabViewScrollable)

You should mention that it can conflict with another gesture, which you could have on TabView.

Comments

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

1 Comment

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.
1

the real problem if your paged horizontal scroll view bounces vertically is its vertical content size is bigger than the scroll view's frame. If you take care of this it won't bounce vertically.

that said, the problem of touching appearance is it affects all the UIScrollViews of the app (if not contained).

a better way to work around this (if you really need to) is using Introspect:

.introspect(.scrollView, on: .iOS(.v17)) { scrollView in
    scrollView.alwaysBounceVertical = false
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.