### SwiftUI Pull-to-Refresh and Load-More Example Source: https://context7.com/wxxsw/refresh/llms.txt This Swift code snippet demonstrates a complete SwiftUI view that integrates both pull-to-refresh and load-more functionalities. It utilizes the Refresh library to manage the UI states for refreshing and loading more data, handling data fetching and state updates with asynchronous operations. ```swift import SwiftUI import Refresh struct CompleteRefreshExample: View { @State private var items: [Item] = [] @State private var headerRefreshing: Bool = false @State private var footerRefreshing: Bool = false @State private var noMoreData: Bool = false @State private var errorMessage: String? struct Item: Identifiable { let id = UUID() let title: String let timestamp: Date } var body: some View { NavigationView { ScrollView { RefreshHeader(refreshing: $headerRefreshing, action: { reloadAllData() }) { HStack(spacing: 12) { if headerRefreshing { ProgressView() Text("Refreshing...") } else if progress > 1.0 { Image(systemName: "arrow.down.circle.fill") Text("Release to refresh") } else { Image(systemName: "arrow.down.circle") .opacity(progress) Text("Pull to refresh") .opacity(progress) } } .font(.subheadline) .foregroundColor(.secondary) .padding() } if let error = errorMessage { Text(error) .foregroundColor(.red) .padding() } ForEach(items) { item in VStack(alignment: .leading, spacing: 4) { Text(item.title) .font(.headline) Text(item.timestamp, style: .relative) .font(.caption) .foregroundColor(.gray) } .frame(maxWidth: .infinity, alignment: .leading) .padding() .background(Color.gray.opacity(0.05)) .cornerRadius(8) .padding(.horizontal) } RefreshFooter(refreshing: $footerRefreshing, action: { loadMoreData() }) { Group { if noMoreData { Label("All caught up!", systemImage: "checkmark.circle") .foregroundColor(.green) } else { HStack { ProgressView() Text("Loading more items...") } } } .font(.subheadline) .foregroundColor(.secondary) .padding() } .noMore(noMoreData) .preload(offset: 80) } .enableRefresh() .navigationTitle("My Feed") .onAppear { if items.isEmpty { reloadAllData() } } } } func reloadAllData() { errorMessage = nil DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { items = generateItems(count: 15, startIndex: 0) headerRefreshing = false noMoreData = false } } func loadMoreData() { DispatchQueue.main.asyncAfter(deadline: .now() + 1) { let newItems = generateItems(count: 10, startIndex: items.count) items.append(contentsOf: newItems) footerRefreshing = false noMoreData = items.count >= 50 } } func generateItems(count: Int, startIndex: Int) -> [Item] { (0.. 5 } } } ``` -------------------------------- ### SwiftUI Pull-to-Refresh and Load More Usage Source: https://github.com/wxxsw/refresh/blob/master/README.md Demonstrates how to implement pull-to-refresh with RefreshHeader and load-more with RefreshFooter in a SwiftUI ScrollView. It shows how to bind refreshing states and define actions for each operation. The .noMore modifier can be used to indicate the end of data, and .preload to trigger loading before reaching the end. ```swift ScrollView { RefreshHeader(refreshing: $headerRefreshing, action: reload) { // Content for header if self.headerRefreshing { Text("refreshing...") } else { Text("Pull to refresh") } } ForEach(items) { YourCell(item: item) } RefreshFooter(refreshing: $footerRefreshing, action: loadMore) { // Content for footer if self.noMore { Text("No more data !") } else { Text("refreshing...") } } .noMore(noMore) .preload(offset: 50) } .enableRefresh() ``` -------------------------------- ### SwiftUI Animated Refresh Animation with Progress Source: https://context7.com/wxxsw/refresh/llms.txt This SwiftUI code demonstrates a custom pull-to-refresh animation. It utilizes the `progress` value from `RefreshHeader` to control the size and rotation of a circle and an arrow, providing visual feedback during the pull action. The `isRefreshing` state and `refreshColors` function manage the actual data refresh. Dependencies include SwiftUI and the Refresh library. ```swift import SwiftUI import Refresh struct AnimatedRefreshView: View { @State private var items: [Color] = [.red, .blue, .green, .orange] @State private var isRefreshing: Bool = false var body: some View { ScrollView { RefreshHeader(refreshing: $isRefreshing, action: refreshColors) { progress in ZStack { if isRefreshing { ProgressView() .scaleEffect(1.5) } else { Circle() .fill(Color.blue.opacity(min(progress, 1.0))) .frame(width: 40 * progress, height: 40 * progress) .rotationEffect(.degrees(360 * progress)) Image(systemName: "arrow.down") .font(.system(size: 20)) .foregroundColor(.white) .opacity(progress > 0.5 ? 1 : 0) .rotationEffect(.degrees(progress > 1.0 ? 180 : 0)) .animation(.spring(), value: progress) } } .frame(height: 60) } ForEach(items, id: \.self) { color in Rectangle() .fill(color) .frame(height: 100) .cornerRadius(10) .padding(.horizontal) } } .enableRefresh() } func refreshColors() { DispatchQueue.main.asyncAfter(deadline: .now() + 2) { items = [.purple, .pink, .yellow, .cyan, .mint] isRefreshing = false } } } ``` -------------------------------- ### SwiftUI Pull-to-Refresh with RefreshHeader Source: https://context7.com/wxxsw/refresh/llms.txt Implements a pull-to-refresh header for ScrollViews using the RefreshHeader component. It allows for custom UI based on pull progress and triggers a data reload action. Dependencies include SwiftUI and the Refresh library. It takes a binding for the refreshing state and an action closure. ```swift import SwiftUI import Refresh struct ContentView: View { @State private var items: [String] = ["Item 1", "Item 2", "Item 3"] @State private var isRefreshing: Bool = false var body: some View { ScrollView { RefreshHeader(refreshing: $isRefreshing, action: { // Perform data reload fetchNewData() }) { // Custom UI based on pull progress if isRefreshing { ProgressView() .padding() } else { Text(progress > 1.0 ? "Release to refresh" : "Pull to refresh") .opacity(progress) .padding() } } ForEach(items, id: \.self) { item in Text(item) .frame(maxWidth: .infinity) .padding() .background(Color.gray.opacity(0.1)) } } .enableRefresh() } func fetchNewData() { DispatchQueue.main.asyncAfter(deadline: .now() + 2) { items = ["New Item 1", "New Item 2", "New Item 3"] isRefreshing = false } } } ``` -------------------------------- ### Enable Basic Pull-to-Refresh in ScrollView Source: https://context7.com/wxxsw/refresh/llms.txt This snippet demonstrates how to activate the pull-to-refresh functionality for a ScrollView using the enableRefresh() modifier. It requires the Refresh library and sets up a RefreshHeader to trigger data loading. The primary input is the ScrollView's content, and the output is the ability to refresh that content. ```swift import SwiftUI import Refresh struct BasicRefreshExample: View { @State private var data: [String] = [] @State private var isRefreshing: Bool = false var body: some View { ScrollView { RefreshHeader(refreshing: $isRefreshing, action: loadData) { progress in Text("Pull progress: \(progress, specifier: \"%.2f\")") } ForEach(data, id: \.self) { item in Text(item) .padding() } } .enableRefresh() // Required to enable refresh functionality .onAppear { loadData() } } func loadData() { DispatchQueue.main.asyncAfter(deadline: .now() + 1) { data = ["Apple", "Banana", "Cherry", "Date", "Elderberry"] isRefreshing = false } } } ``` -------------------------------- ### SwiftUI Load More with RefreshFooter Source: https://context7.com/wxxsw/refresh/llms.txt Adds infinite scroll functionality to ScrollViews using the RefreshFooter component. It triggers a load more action when the user scrolls near the bottom, supporting custom loading indicators and a 'no more data' state. Dependencies include SwiftUI and the Refresh library. It takes a binding for the loading state and an action closure. ```swift import SwiftUI import Refresh struct InfiniteScrollView: View { @State private var items: [Int] = Array(1...20) @State private var isLoadingMore: Bool = false @State private var hasMoreData: Bool = true var body: some View { ScrollView { RefreshHeader(refreshing: $isLoadingMore, action: { resetData() }) { ProgressView() .opacity(isLoadingMore ? 1 : 0) } ForEach(items, id: \.self) { item in Text("Item \(item)") .frame(height: 60) .frame(maxWidth: .infinity) .background(Color.blue.opacity(0.1)) } RefreshFooter(refreshing: $isLoadingMore, action: { loadMoreItems() }) { if hasMoreData { HStack { ProgressView() Text("Loading more...") } .padding() } else { Text("No more data") .foregroundColor(.gray) .padding() } } .noMore(!hasMoreData) .preload(offset: 50) } .enableRefresh() } func loadMoreItems() { DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { let currentCount = items.count let newItems = Array((currentCount + 1)...(currentCount + 10)) items.append(contentsOf: newItems) isLoadingMore = false hasMoreData = items.count < 50 } } func resetData() { DispatchQueue.main.asyncAfter(deadline: .now() + 1) { items = Array(1...20) hasMoreData = true isLoadingMore = false } } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.