支持拉取刷新的 SwiftUI 滚动视图

可刷新滚动视图

在 SwiftUI 中,目前只能使用拉取来刷新视图。此包提供了一个可刷新的自定义滚动视图,以便您可以拉取以刷新所需的任何 SwiftUI 视图。 它响应修饰符,因此使用它的方式与刷新列表的方式完全相同。List.refreshable()

它还支持传入自定义,以便您可能拥有具有自定义外观的加载器。UIRefreshControl

演示

How does it work?

This view works by wrapping internally and putting your SwiftUI view in a UIHostingController within the scroll view.UIScrollView

Examples

A full sample project with various refreshable views is available at: https://github.com/Q42/RefreshableScrollViewDemo

Basic example

struct CustomView: View {
  var body: some View {
    RefreshableScrollView {
      Text("Hello, World!")
    }
    .refreshable {
      do {
        // Sleep for 2 seconds
        try await Task.sleep(nanoseconds: 2 * 1_000_000_000)
      } catch {}
    }
  }
}

Lazy VStack

struct StackView: View {
  struct Item: Identifiable {
    let id: Int
  }
  @State var items: [Item] = Array(1...100).map(Item.init)
  @State var count = 100

  var body: some View {
    RefreshableScrollView {
      LazyVStack(alignment: .leading) {
        ForEach(items) { item in
          Text("Row \(item.id)")
        }
      }
    }
    .refreshable {
      do {
        // Sleep for 2 seconds
        try await Task.sleep(nanoseconds: 2 * 1_000_000_000)
      } catch {}
      
      count += 1
      items.insert(Item(id: count), at: 0)
    }
  }
}

Lazy VGrid

struct GridView: View {
  let columns: [GridItem] = Array(repeating: .init(.flexible()), count: 2)

  var body: some View {
    RefreshableScrollView {
      LazyVGrid(columns: columns) {
        ForEach((0...79), id: \.self) {
          let codepoint = $0 + 0x1f600
          let codepointString = String(format: "%02X", codepoint)
          Text("\(codepointString)")
          let emoji = String(Character(UnicodeScalar(codepoint)!))
          Text("\(emoji)")
        }
      }.font(.largeTitle)
    }
    .refreshable {
      do {
        // Sleep for 2 seconds
        try await Task.sleep(nanoseconds: 2 * 1_000_000_000)
      } catch {}
    }
  }
}

GitHub

点击跳转