我尝试了许多不同的解决方案,但对我的情况没有任何效果。
GeometryReader
基于解决方案的复杂布局表现不佳。
这是一个纯粹的 SwiftUI 2.0 视图,它似乎运行良好,不会随着不断的状态更新而降低滚动性能,并且不使用任何 UIKit hack:
import SwiftUI
struct PullToRefreshView: View
{
private static let minRefreshTimeInterval = TimeInterval(0.2)
private static let triggerHeight = CGFloat(100)
private static let indicatorHeight = CGFloat(100)
private static let fullHeight = triggerHeight + indicatorHeight
let backgroundColor: Color
let foregroundColor: Color
let isEnabled: Bool
let onRefresh: () -> Void
@State private var isRefreshIndicatorVisible = false
@State private var refreshStartTime: Date? = nil
init(bg: Color = .white, fg: Color = .black, isEnabled: Bool = true, onRefresh: @escaping () -> Void)
{
self.backgroundColor = bg
self.foregroundColor = fg
self.isEnabled = isEnabled
self.onRefresh = onRefresh
}
var body: some View
{
VStack(spacing: 0)
{
LazyVStack(spacing: 0)
{
Color.clear
.frame(height: Self.triggerHeight)
.onAppear
{
if isEnabled
{
withAnimation
{
isRefreshIndicatorVisible = true
}
refreshStartTime = Date()
}
}
.onDisappear
{
if isEnabled, isRefreshIndicatorVisible, let diff = refreshStartTime?.distance(to: Date()), diff > Self.minRefreshTimeInterval
{
onRefresh()
}
withAnimation
{
isRefreshIndicatorVisible = false
}
refreshStartTime = nil
}
}
.frame(height: Self.triggerHeight)
indicator
.frame(height: Self.indicatorHeight)
}
.background(backgroundColor)
.ignoresSafeArea(edges: .all)
.frame(height: Self.fullHeight)
.padding(.top, -Self.fullHeight)
}
private var indicator: some View
{
ProgressView()
.progressViewStyle(CircularProgressViewStyle(tint: foregroundColor))
.opacity(isRefreshIndicatorVisible ? 1 : 0)
}
}
当它进入或离开屏幕边界时,它使用LazyVStack
负填充来调用onAppear
和onDisappear
触发视图。Color.clear
如果触发视图出现和消失之间的时间大于minRefreshTimeInterval
允许在ScrollView
不触发刷新的情况下反弹,则触发刷新。
要使用它,请添加PullToRefreshView
到顶部ScrollView
:
import SwiftUI
struct RefreshableScrollableContent: View
{
var body: some View
{
ScrollView
{
VStack(spacing: 0)
{
PullToRefreshView { print("refreshing") }
// ScrollView content
}
}
}
}
要点:https ://gist.github.com/tkashkin/e5f6b65b255b25269d718350c024f550