SwiftUI 2.0 TabView 禁用滑动以更改页面

SwiftUI 2.0 TabView disable swipe to change page

我有一个使用 swiftUI 2.0 PageTabViewStyle 的 TabView。有没有办法禁止滑动换页?

我的第一个选项卡视图中有一个搜索栏,但如果用户正在输入,我不想让他们能够改变他们的状态,我基本上希望它被锁定在那个屏幕上,直到所述功能已完成。

这是一个显示不同之处的 gif,我希望在 gif 中全屏时禁用选项卡更改。 https://imgur.com/GrqcGCI

尝试如下操作(使用一些存根代码进行测试)。这个想法是在某些情况(在你开始编辑的情况下)发生时阻止选项卡视图拖动手势

@State var isSearching = false

// ... other code

TabView {
    // ... your code here

    Your_View()
       .gesture(isSearching ? DragGesture() : nil)  // blocks TabView gesture !!
}
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .always))

对于任何试图解决这个问题的人,我设法通过将 TabView 状态设置为禁用来做到这一点。

TabView(selection: $currentIndex.animation()) {
    Items()
 }.disabled(true)
 

编辑:如评论中所述,这也将禁用 TabView 中的所有内容

我尝试了 Asperis 的解决方案,但我仍然无法禁用滑动,并且将 disabled 添加到 true 也不起作用,因为我希望子视图具有交互性。对我有用的解决方案是使用 Majid (https://swiftwithmajid.com/2019/12/25/building-pager-view-in-swiftui/) 的自定义寻呼机视图并添加一个条件,如 Asperi 的解决方案。

Majid 的带条件的 PagerView:

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)
                    }
            )
        }
    }
    
}

内容视图:

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")
                }

            }
            
        }
        
    }
    
}