0

我正在使用下面的代码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)
                }
            }
            
        }
    }
}
     
4

0 回答 0