はじめに
refreshableをカスタムするためにはScrollViewのスクロール位置を調べたり、RefreshActionをいじったりと、色々面倒なことが多いです。
手軽に済ませたい場合はUIKitをいじっちゃうのが手っ取り早いです。
サンプルアプリ
カスタムローディングの実装
import SwiftUI
enum CustomProgress: CaseIterable {
case state1
case state2
}
extension CustomProgress {
var rotationEffect: Angle {
return switch self {
case .state1: .degrees(0)
case .state2: .degrees(360)
}
}
}
struct CustomProgressView: View {
var body: some View {
PhaseAnimator(CustomProgress.allCases) { phase in
Image(systemName: "cross.fill")
.resizable()
.scaledToFit()
.foregroundStyle(.green)
.rotationEffect(phase.rotationEffect)
}
}
static var uiView: UIView {
let progressViewSize: CGFloat = 30
let view = CustomProgressView().frame(width: progressViewSize, height: progressViewSize)
let viewController = UIHostingController(rootView: view)
viewController.view.frame = .init(x: (UIScreen.main.bounds.width / 2) - (progressViewSize / 2), y: 10, width: progressViewSize, height: progressViewSize)
viewController.view.backgroundColor = .clear
return viewController.view
}
}
使用側の実装
import SwiftUI
struct ContentView: View {
init() {
// 元のローディングを透明にする
UIRefreshControl.appearance().tintColor = .clear
// カスタムのローディングを設定
UIRefreshControl.appearance().addSubview(CustomProgressView.uiView)
}
var body: some View {
List {
ForEach(0..<50) { index in
Text("index: \(index)")
}
}
.refreshable {
print("更新")
}
}
}
おわり
今回紹介した方法ではアプリ全体に影響してしまいます。
カスタムローディングを作成するためにPhaseAnimator
を使用しています。
PhaseAnimator
については以下の記事を見てください。