A customizable, native SwiftUI refresh control for iOS 14+
If you want to see it in a real app, check out dateit
Also works well with ScrollViewLoader
First add the package to your project.
import Refresher
struct DetailsView: View {
@State var refreshed = 0
var body: some View {
ScrollView {
Text("Details!")
Text("Refreshed: \(refreshed)")
}
.refresher { // Called when pulled to refresh
await Task.sleep(seconds: 2)
refreshed += 1
}
}
}
async
/await
compatible - even on iOS 14DispatchQueue
operations.default
and .system
styles (see below for details)See: Examples for a full sample project with multiple implementations
Refresher
plays nice with both Navigation views and navigation subviews.
Refresher
supports an overlay mode to show a refresh indicator over fixed position content
.refresher(overlay: true)
Refresher
's default animation is designed to be more flexible than the system animation style. If you want Refresher
to behave more like they system refresh control, you can change the style:
.refresher(style: .system) { done in
Refresher can take a custom spinner view. Your custom view will get a binding instances of the refresher state that contains useful properties for managing animations and translations. Here is a custom spinner that shows an emoji:
public struct EmojiRefreshView: View {
@Binding var state: RefresherState
@State private var angle: Double = 0.0
@State private var isAnimating = false
var foreverAnimation: Animation {
Animation.linear(duration: 1.0)
.repeatForever(autoreverses: false)
}
public var body: some View {
VStack {
switch state.mode {
case .notRefreshing:
Text("🤪")
.onAppear {
isAnimating = false
}
case .pulling:
Text("😯")
.rotationEffect(.degrees(360 * state.dragPosition))
case .refreshing:
Text("😂")
.rotationEffect(.degrees(self.isAnimating ? 360.0 : 0.0))
.onAppear {
withAnimation(foreverAnimation) {
isAnimating = true
}
}
}
}
.scaleEffect(2)
}
}
Add the custom refresherView:
.refresher(refreshView: EmojiRefreshView.init ) { done in
If you prefer to call a completion to stop the refresher:
.refresher(style: .system) { done in
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) {
refreshed += 1
done() // Call done to stop the refresher
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。