ScrollViewProxy 1.0.3

ScrollViewProxy 1.0.3

Amzd 维护。



  • Casper Zandbergen

截至6月22日,这已包含在 SwiftUI 2 测试版中。https://developer.apple.com/documentation/swiftui/scrollviewproxy

苹果实现只使用 .id(_:),我与此有一些更新问题,其中具有 ID 的视图有时在其 ObservedObject 发生变化时不会更新。也许这在新 SwiftUI 2 测试版中已得到修复。

此外,苹果实现仅支持 iOS 14,因此我认为此存储库对向后兼容仍然很有用。

ScrollViewProxy

添加 ScrollViewReaderScrollViewProxy,帮助您在 ScrollView 中滚动到特定位置

要获取 ScrollViewProxy,您可以使用 ScrollView 的便捷初始化方法

ScrollView { proxy in
    ...
}

或将 ScrollViewReader 添加到任何在底层创建 UIScrollView 的 View

List {
    ScrollViewReader { proxy in
        ...
    }
}

ScrollViewProxy 当前有一个变量和两个您可以调用的函数

/// A publisher that publishes changes to the scroll views offset
public var offset: OffsetPublisher

/// Scrolls to an edge or corner
public func scrollTo(_ alignment: Alignment, animated: Bool = true)

/// Scrolls the view with ID to an edge or corner
public func scrollTo(_ id: ID, alignment: Alignment = .top, animated: Bool = true)

要使用滚动到 ID 的函数,您必须将 ID 添加到您想要滚动的视图

ScrollView { proxy in
    HStack { ... }
        .scrollId("someId")
}

这是与 SwiftUI 2.0 实现不同的唯一部分,因为我不知道如何从 .id(_:) 函数访问具有 ID 的视图

示例

将所有内容汇集在一个示例中

struct ScrollViewProxyExample: View {
    
    @State var randomInt = Int.random(in: 0..<200)
    @State var proxy: ScrollViewProxy? = nil
    @State var offset: CGPoint = .zero
    
    var body: some View {
        // GeometryReader for safeAreaInsets on Sticky View
        GeometryReader { geometry in 
            VStack {
                ScrollView { proxy in
                    Text("Sticky View")
                        .background(Color.white)
                        .onReceive(proxy.offset) { self.offset = $0 }
                        .offset(x: offset.x, y: offset.y + geometry.safeAreaInsets.top)
                        .zIndex(1)
                    
                    VStack(spacing: 20) {
                        ForEach(0..<200) { index in
                            HStack {
                                Spacer()
                                Text("Item: \(index)").font(.title)
                                Spacer()
                            }.scrollId(index)
                        }
                    }
                    .zIndex(0)
                    .onAppear {
                        self.proxy = proxy
                    }
                }
                HStack {
                    Button(action: {
                        self.proxy?.scrollTo(self.randomInt, alignment: .center)
                        self.randomInt = Int.random(in: 0..<200)
                    }, label: {
                        Text("Go to \(self.randomInt)")
                    })
                    Spacer()
                    Button(action: { self.proxy?.scrollTo(.bottom) }, label: {
                        Text("Bottom")
                    })
                    Spacer()
                    Button(action: { self.proxy?.scrollTo(.center) }, label: {
                        Text("Center")
                    })
                }.padding()
            }
        }
    }
}

解耦

想要放弃对 iOS 13 的支持并迁移到 SwiftUI 2.0 版本吗?

  1. 移除包
  2. 添加此扩展
extension View {
    public func scrollId<ID: Hashable>(_ id: ID) -> some View {
        id(id)
    } 
}

(或将所有 .scrollId 替换为 .id)