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")
}
}
}
}
}
我有一个使用 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")
}
}
}
}
}