![見出し画像](https://assets.st-note.com/production/uploads/images/95390636/rectangle_large_type_2_0afa3b2d1af45305f037bbd23eae21e1.png?width=1200)
SwiftUIのProgressViewをカスタマイズ
ProgressViewとは?
ProgressViewはiOS 14以上から利用でき、タスク完了までの進捗状況を表すことができる。
struct ContentView: View {
@State private var progress = 0.5
var body: some View {
ProgressView("Downloading...", value: progress)
}
}
スタイル
ProgressViewにはデフォルトで用意されているスタイル(ProgressViewStyle)があり、シーンに応じて表示スタイルを指定することができる。
DefaultProgressViewStyle:コンテキストに応じてスタイルを自動選択
CircularProgressViewStyle:UIActivityIndicatorのような円形のスタイル
LinearProgressViewStyle:横棒で表示されるスタイル
CircularProgressViewStyle
.progressViewStyle(.circular)で指定できるが、init()だけでも自動的に円形スタイルとなる。また、カラーを変更したい場合は.tintや.backgroundでColorを指定すればよい。
struct ContentView: View {
var body: some View {
VStack(spacing: 40) {
// initだけの場合は、自動的に円形スタイルになる
ProgressView()
// アクセントカラーなどを指定してカスタマイズできる
ProgressView()
.progressViewStyle(.circular)
.padding()
.tint(Color.white)
.background(Color.gray)
.cornerRadius(8)
.scaleEffect(1.2)
}
.padding()
}
}
![](https://assets.st-note.com/img/1673412272520-zQeGTtHzJm.png)
LinearProgressViewStyle
.progressViewStyle(.linear)で横棒スタイルを指定でき、上記と同様にラベルやアクセントカラーなどを変更できる。
struct ContentView: View {
@State private var progress = 0.5
var body: some View {
VStack(spacing: 40) {
// ラベル付きで進捗率を示す
ProgressView("Downloading...", value: progress)
// ラベルやアクセントカラーなどを指定してカスタマイズできる
ProgressView("Downloading...", value: progress)
.progressViewStyle(.linear)
.foregroundColor(.gray)
.tint(Color.orange)
}
.padding()
}
}
![](https://assets.st-note.com/img/1673412295382-I61EB3gm6J.png)
カスタムスタイル
より自由にProgressViewをカスタマイズしたい場合は、ProgressViewStyleプロトコルに準拠したスタイルを定義して、makeBody(configuration:)を実装すればよい。
struct GaugeProgressStyle: ProgressViewStyle {
var color: Color
var lineWidth: CGFloat
func makeBody(configuration: Configuration) -> some View {
let fractionCompleted = configuration.fractionCompleted ?? 0
return ZStack {
Circle()
.trim(from: 0, to: fractionCompleted)
.stroke(color, style: StrokeStyle(lineWidth: lineWidth, lineCap: .round))
// trimでは右が起点なので、反時計回りに90°回転させる
.rotationEffect(.degrees(-90))
}
}
}
struct ContentView: View {
@State private var progress = 0.6
var body: some View {
VStack(spacing: 40) {
ProgressView(value: progress)
.progressViewStyle(GaugeProgressStyle(color: .blue, lineWidth: 8))
.frame(width: 40, height: 40)
}
.padding()
}
}
![](https://assets.st-note.com/img/1673412303367-rAYgot0lLl.png)
補足
UIActivityIndicatorのような円形スタイルは、valueなしのProgressViewで実現できるが、iOS13以下もサポートする場合はProgressViewが使えないので、UIActivityIndicatorViewをラップする方法がある。
import SwiftUI
struct ActivityIndicator: UIViewRepresentable {
var style: UIActivityIndicatorView.Style = .medium
func makeUIView(context: UIViewRepresentableContext<ActivityIndicator>) -> UIActivityIndicatorView {
UIActivityIndicatorView(style: style)
}
func updateUIView(_ uiView: UIActivityIndicatorView, context: UIViewRepresentableContext<ActivityIndicator>) {
uiView.startAnimating()
}
}
struct ContentView: View {
var body: some View {
ActivityIndicator()
}
}
サンプルコード
参考
この記事が気に入ったらサポートをしてみませんか?