我正在使用下面的代码PagerView
(来自此 Github Gist 的评论)来创建一个页面滑动 UI,它工作得非常好,并且比使用滑动过渡非常跳跃的情况要平滑TabView
得多.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
。但是,当我ScrollView
在包含它的视图周围环绕时,PagerView
它不会让我在每个PagerView
页面内的子视图上垂直滚动。我注释掉了动画,PagerView
没有任何改变,所以我不认为就是这样。任何其他想法是什么阻止我垂直滚动?
struct PagerView<Content: View>: View {
let pageCount: Int
@State var ignore: Bool = false
@Binding var currentIndex: Int {
didSet {
if (!ignore) {
currentFloatIndex = CGFloat(currentIndex)
}
}
}
@State var currentFloatIndex: CGFloat = 0 {
didSet {
ignore = true
currentIndex = min(max(Int(currentFloatIndex.rounded()), 0), self.pageCount - 1)
ignore = false
}
}
let content: Content
@GestureState private var offsetX: CGFloat = 0
init(pageCount: Int, currentIndex: Binding<Int>, @ViewBuilder content: () -> Content) {
self.pageCount = pageCount
self._currentIndex = currentIndex
self.content = content()
}
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.currentFloatIndex) * geometry.size.width)
.offset(x: self.offsetX)
.highPriorityGesture(
DragGesture().updating(self.$offsetX) { value, state, _ in
state = value.translation.width
}
.onEnded({ (value) in
let offset = value.translation.width / geometry.size.width
let offsetPredicted = value.predictedEndTranslation.width / geometry.size.width
let newIndex = CGFloat(self.currentFloatIndex) - offset
self.currentFloatIndex = newIndex
withAnimation(.easeOut) {
if(offsetPredicted < -0.5 && offset > -0.5) {
self.currentFloatIndex = CGFloat(min(max(Int(newIndex.rounded() + 1), 0), self.pageCount - 1))
} else if (offsetPredicted > 0.5 && offset < 0.5) {
self.currentFloatIndex = CGFloat(min(max(Int(newIndex.rounded() - 1), 0), self.pageCount - 1))
} else {
self.currentFloatIndex = CGFloat(min(max(Int(newIndex.rounded()), 0), self.pageCount - 1))
}
}
})
)
}
.onChange(of: currentIndex, perform: { value in
//print("index changed")
// this is probably animated twice, if the tab change occurs because of the drag gesture
withAnimation(.easeOut) {
currentFloatIndex = CGFloat(value)
}
})
}
}
var body: some View {
NavigationView {
ScrollView {
VStack {
HStack {
//Omitted
}
PagerView(pageCount: 3, currentIndex: $currentPage) {
FirstView().tag(currentPage) //these views are all larger than the screen and need to be scrolled to see all content
SecondView().tag(currentPage)
ThirdView().tag(currentPage)
}
}
}
}
}