如何在 swiftui 中拖动以刷新网格视图?我知道你可以在 iOS 15 中使用带有可刷新修饰符的列表视图来做到这一点,但是你如何使用 LazyVGrid 来做到这一点?您将如何在 iOS 15 之前的列表或网格视图中执行此操作?我在 swiftui 很新。我附上了一个 gif,显示了我试图实现的目标。
问问题
243 次
1 回答
1
这是代码LazyVStack
:
import SwiftUI
struct PullToRefreshSwiftUI: View {
@Binding private var needRefresh: Bool
private let coordinateSpaceName: String
private let onRefresh: () -> Void
init(needRefresh: Binding<Bool>, coordinateSpaceName: String, onRefresh: @escaping () -> Void) {
self._needRefresh = needRefresh
self.coordinateSpaceName = coordinateSpaceName
self.onRefresh = onRefresh
}
var body: some View {
HStack(alignment: .center) {
if needRefresh {
VStack {
Spacer()
ProgressView()
Spacer()
}
.frame(height: 100)
}
}
.background(GeometryReader {
Color.clear.preference(key: ScrollViewOffsetPreferenceKey.self,
value: $0.frame(in: .named(coordinateSpaceName)).origin.y)
})
.onPreferenceChange(ScrollViewOffsetPreferenceKey.self) { offset in
guard !needRefresh else { return }
if abs(offset) > 50 {
needRefresh = true
onRefresh()
}
}
}
}
struct ScrollViewOffsetPreferenceKey: PreferenceKey {
typealias Value = CGFloat
static var defaultValue = CGFloat.zero
static func reduce(value: inout Value, nextValue: () -> Value) {
value += nextValue()
}
}
这是典型的用法:
struct ContentView: View {
@State private var refresh: Bool = false
@State private var itemList: [Int] = {
var array = [Int]()
(0..<40).forEach { value in
array.append(value)
}
return array
}()
var body: some View {
ScrollView {
PullToRefreshSwiftUI(needRefresh: $refresh,
coordinateSpaceName: "pullToRefresh") {
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
withAnimation { refresh = false }
}
}
LazyVStack {
ForEach(itemList, id: \.self) { item in
HStack {
Spacer()
Text("\(item)")
Spacer()
}
}
}
}
.coordinateSpace(name: "pullToRefresh")
}
}
这可以很容易地适应LazyVGrid
,只需更换LazyVStack
。
于 2022-01-28T13:44:43.247 回答