4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【SwiftUI】「読み込み中...」の「...」のみアニメーションさせる

Last updated at Posted at 2023-12-12

こんにちは。ymurao2です!
「読み込み中...」のような文字列で、末尾の「...」のみアニメーションさせたいときがあると思います。
今回はこちらをご紹介します。

Simulator Screen Recording - iPhone 15 Pro - 2023-12-12 at 20.50.33.gif

全体像

コードだけ見たい方、お忙しい方のためにまずは全体像です。

struct AnimatedTextView: View {
    @State private var dotCount = 0
    var dots: String {
        String(repeating: ".", count: dotCount)
    }
    
    let timer = Timer.publish(every: 0.3, on: .main, in: .common).autoconnect()
    
    var body: some View {
        HStack(spacing: 0) {
            Text("読み込み中")
                .font(.title)
                .foregroundStyle(Color.gray)
            Text("...")
                .font(.title)
                .hidden()
                .overlay {
                    Text(dots)
                        .font(.title)
                        .foregroundStyle(Color.gray)
                        .frame(maxWidth: .infinity, alignment: .leading)
                        .onReceive(timer) { _ in
                            if dotCount < 3 {
                                dotCount += 1
                            } else {
                                dotCount = 1
                            }
                        }
                }
        }
    }
}

おわり

以上です。結構簡単に実装できました!

解説

順を追って解説します。

1. まず「読み込み中...」を用意します

HStackで書くのがミソですね

HStack(spacing: 0) {
    Text("読み込み中")
        .font(.title)
        .foregroundStyle(Color.gray)
    Text("...")
        .font(.title)
}

Screenshot 2023-12-12 at 20.53.22.png

2. 「...」を非表示にします

「...」の領域を確保するために.hiddenモディファイアを使用してViewを非表示にします
このとき実際に表示する「...」と大きさを揃えるために.fontで大きさを調整しています

HStack(spacing: 0) {
    Text("読み込み中")
        .font(.title)
        .foregroundStyle(Color.gray)
    Text("...")
        .font(.title)
+       .hidden()
}

Screenshot 2023-12-12 at 20.56.44.png

3. .overlayモディファイアで「...」の上に「...」を表示する

HStack(spacing: 0) {
    Text("読み込み中")
        .font(.title)
        .foregroundStyle(Color.gray)
    Text("...")
        .font(.title)
        .hidden()
+       .overlay {
+           Text("...")
+               .font(.title)
+               .foregroundStyle(Color.gray)
+       }
}

Screenshot 2023-12-12 at 21.01.54.png

4. アニメーションさせる

0.3秒ごとにアクションを発火させ、dotCountを増やすことで、いい感じにアニメーションさせています

+ @State private var dotCount = 0
+ var dots: String {
+     String(repeating: ".", count: dotCount)
+ }

// 0.3秒ごとに発火
+ let timer = Timer.publish(every: 0.3, on: .main, in: .common).autoconnect()

var body: some View {
    HStack(spacing: 0) {
        Text("読み込み中")
            .font(.title)
            .foregroundStyle(Color.gray)
        Text("...")
            .font(.title)
            .hidden()
            .overlay {
                Text(dots)
                    .font(.title)
                    .foregroundStyle(Color.gray)
+                   .frame(maxWidth: .infinity, alignment: .leading)
+                   // timerを監視
+                   .onReceive(timer) { _ in
+                       if dotCount < 3 {
+                           dotCount += 1
+                       } else {
+                           dotCount = 1
+                       }
+                   }
            }
    }
}

この記事がお役に立てば、ぜひいいね👍お願いします!

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?