如何知道 SwiftUI 中的scrollView是否已停止?

问题描述 投票:0回答:1

我该如何处理 swiftUI 中的scrollViewDidEndDecelerating 和scrollViewDidEndDragging 函数

我想设置scrollView的位置,使得scrollView停止移动时selectedIndex位于中间。

struct ContentView: View {
    
    @State private var imageList: [String] = ["Onur","Onur","Onur","Onur","Onur","Onur","Onur","Onur","Onur"]
    private var spacing: CGFloat = UIScreen.main.bounds.width / 2 - 100
    @State private var moffsetX: CGFloat = 0
    @State private var oldFffsetX: CGFloat = 0
    @State private var isScrolling: Bool = false
    @State private var selectedIndex: Int = 0
    
    func horizontalScrollView() -> some View {
        ScrollView(.horizontal){
            Spacer()
            HStack(spacing: spacing){
                Spacer()
                    .frame(width: 50)
                ForEach(imageList, id:\.self){ image in
                    Image(image)
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                        .frame(width: 100,height: 100)
                        .clipShape(Circle())
                        .overlay(Circle().stroke(.blue,lineWidth: 4))
                }
                
                Spacer()
                    .frame(width: 50)
            }
            
            .overlay(GeometryReader{ geometry in
                Color.clear.onChange(of: geometry.frame(in: .global).minX) { value, newValue in
                    oldFffsetX = value
                    moffsetX = newValue
                    let index = Int(round(geometry.frame(in: .global).minX / (-1 * (100 + spacing))))
                    if index != selectedIndex{
                        if index < 0{
                            selectedIndex = 0
                        } else if index > imageList.count - 1{
                            selectedIndex = imageList.count - 1
                        } else{
                            selectedIndex = index
                        }
                    }
                    isScrolling = true
                }
            })
            
            Spacer()
        }
        
        
    }
}
ios swift swiftui scrollview
1个回答
0
投票

您可以考虑使用 CurrentValueSubjectAnyPublisher 来检测滚动事件。这是用例的演示,

struct ScrollDetectorView: View {
let scrollSubject: CurrentValueSubject<CGFloat, Never>
let publisher: AnyPublisher<CGFloat, Never>

init() {
    let scrollSubject = CurrentValueSubject<CGFloat, Never>(0)
    self.publisher = scrollSubject
        .debounce(for: .seconds(0.3), scheduler: DispatchQueue.main)
        .dropFirst()
        .eraseToAnyPublisher()
    self.scrollSubject = scrollSubject
}

var body: some View {
    ScrollView {
        VStack(spacing: 5) {
            ForEach(0...200, id: \.self) { i in
                Text("\(i)")
                    .frame(width: 200, height: 100)
                    .background(Color.green)
            }
        }
        .onPreferenceChange(ViewOffsetKey.self) { scrollSubject.send($0) }
    }.coordinateSpace(name: "scroll")
    .onReceive(publisher) {
        print("Scroll did end: \($0)")
    }
}
}
struct ViewOffsetKey: PreferenceKey {
    typealias Value = CGFloat
    static var defaultValue = CGFloat.zero
    static func reduce(value: inout Value, nextValue: () -> Value) {
        value += nextValue()
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.