Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI 2.0 TabView disable swipe to change page

I have a TabView thats using the swiftUI 2.0 PageTabViewStyle. Is there any way to disable the swipe to change pages?

I have a search bar in my first tab view, but if a user is typing, I don't want to give the ability to change they are on, I basically want it to be locked on to that screen until said function is done.

Here's a gif showing the difference, I'm looking to disable tab changing when it's full screen in the gif. https://imgur.com/GrqcGCI

like image 896
daee kang Avatar asked Jul 30 '20 07:07

daee kang


Video Answer


2 Answers

I tried Asperis's solution, but I still couldn't disable the swiping, and adding disabled to true didn't work since I want the child views to be interactive. The solution that worked for me was using Majid's (https://swiftwithmajid.com/2019/12/25/building-pager-view-in-swiftui/) custom Pager View and adding a conditional like Asperi's solution.

Majid's PagerView with conditional:

import SwiftUI

struct PagerView<Content: View>: View {
    let pageCount: Int
    @Binding var canDrag: Bool
    @Binding var currentIndex: Int
    let content: Content
    
    
    init(pageCount: Int, canDrag: Binding<Bool>, currentIndex: Binding<Int>, @ViewBuilder content: () -> Content) {
        self.pageCount = pageCount
        self._canDrag = canDrag
        self._currentIndex = currentIndex
        self.content = content()
    }
    
    
    @GestureState private var translation: CGFloat = 0
    
    var body: some View {
        GeometryReader { geometry in
            HStack(spacing: 0) {
                self.content.frame(width: geometry.size.width)
            }
            .frame(width: geometry.size.width, alignment: .leading)
            .offset(x: -CGFloat(self.currentIndex) * geometry.size.width)
            .offset(x: self.translation)
            .animation(.interactiveSpring(), value: currentIndex)
            .animation(.interactiveSpring(), value: translation)
            .gesture(!canDrag ? nil : // <- here
                
                DragGesture()
                    .updating(self.$translation) { value, state, _ in
                        
                        state = value.translation.width
                    }
                    .onEnded { value in
                        let offset = value.translation.width / geometry.size.width
                        let newIndex = (CGFloat(self.currentIndex) - offset).rounded()
                        self.currentIndex = min(max(Int(newIndex), 0), self.pageCount - 1)
                    }
            )
        }
    }
    
}

ContentView:

import SwiftUI

struct ContentView: View {
    
    
    @State private var currentPage = 0
    @State var canDrag: Bool = true
    
    
    var body: some View {
        
        PagerView(pageCount: 3, canDrag: $canDrag, currentIndex: $currentPage) {
            VStack {
                Color.blue
                
                
                Button {
                    canDrag.toggle()
                } label: {
                    Text("Toogle drag")
                }

            }
            
            VStack {
                Color.red
                
                
                Button {
                    canDrag.toggle()
                } label: {
                    Text("Toogle drag")
                }

            }
            
            VStack {
                Color.green
                
                
                Button {
                    canDrag.toggle()
                } label: {
                    Text("Toogle drag")
                }

            }
            
        }
        
    }
    
}
like image 152
vebbis Avatar answered Nov 08 '22 22:11

vebbis


Try something like the following (tested with some stub code). The idea is to block tab view drag gesture when some condition (in you case start editing) happens

@State var isSearching = false

// ... other code

TabView {
    // ... your code here

    Your_View()
       .gesture(isSearching ? DragGesture() : nil)  // blocks TabView gesture !!
}
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .always))
like image 20
Asperi Avatar answered Nov 08 '22 21:11

Asperi