【SwiftUI】Apple 公式サンプルでは Animation と Transition をどのように組み合わせているのか

画面上にメッセージを表示する View。


import SwiftUI

struct Message: View {
  var text: String

  var body: some View {
    HStack(spacing: 0) {
      Image(systemName: "heart.fill")
        .foregroundStyle(.red)
        .font(.title)
        .padding()
      Text(text)
        .padding(.trailing, 24)
    }
    .clipShape(.capsule)
    .background(
      .regularMaterial.shadow(.drop(radius: 16)),
      in: .capsule
    )
  }
}

#Preview {
  Message(text: "Hello, world!")
}

どのように、アニメーションやトランジションをつけて、生き生きとした画面にしているか。

Apple 公式サンプルを参考に書いてみます。

 

🧑🏻‍💻 Preview 用 View の準備

挙動を何度も確かめるために、

Preview 専用の View を作っておきます。


private struct RefreshPreview: View {
  var text: String

  @State private var id = false

  var body: some View {
    Message(text: text)
      .id(id)

    Button("Refresh") {
      id.toggle()
    }
    .buttonStyle(.borderedProminent)
  }
}

👉 【SwiftUI】View の 強制再描画 hatena-bookmark

ボタンを押すと強制的に画面再描画がされて、

表示開始からの動きを確認できるようになります。

 

🧑🏻‍💻 まずは アニメーション・トランジションなしでつくる


import SwiftUI

struct Message: View {
  var text: String

  @State private var showIcon = false
  @State private var showText = false

  var body: some View {
    HStack(spacing: 0) {
      if showIcon {
        Image(systemName: "heart.fill")
          .foregroundStyle(.red)
          .font(.title)
          .padding()
      }
      if showText {
        Text(text)
          .padding(.trailing, 24)
      }
    }
    .clipShape(.capsule)
    .background(
      .regularMaterial.shadow(.drop(radius: 16)),
      in: .capsule
    )
    .frame(height: 50)
    .onAppear {
      Task {
        showIcon = true
        try await Task.sleep(for: .seconds(1))
        showText = true
        try await Task.sleep(for: .seconds(1))
        showText = false
        try await Task.sleep(for: .seconds(1))
        showIcon = false
      }
    }
  }
}

private struct RefreshPreview: View {
  var text: String

  @State private var id = false

  var body: some View {
    Message(text: text)
      .id(id)

    Button("Refresh") {
      id.toggle()
    }
    .buttonStyle(.borderedProminent)
  }
}

#Preview {
  RefreshPreview(text: "Hello, world !!!")
    .padding()
    .frame(maxWidth: .infinity)
}

アイコン画像とテキスト部分をそれぞれの @State で


アイコン表示 

  ↓

テキスト表示

  ↓

テキスト非表示

  ↓

アイコン非表示

と Task の中で1秒ごとに変化させています。

しかし、アニメーションやトランジションがないので、

スムーズに View が変化しません。

 

🧑🏻‍💻 アニメーション・トランジションをつける



 

🧑🏻‍💻 まとめ

やっぱ、全然違いますね。

👉 sample-backyard-birds/Multiplatform/Birds/BirdFoodHappinessIndicator.swift at main · apple/sample-backyard-birds hatena-bookmark

 

🧑🏻‍💻 追記: 上記のトランジションっている ?

withAnimation() 記述は必要だとして、

transition() 記述は不要なのではないか。

できるだけシンプルにテンプレート化しておきたいので、

0.25 倍の速度で確認してみます。

上がトランジションなし、

下がトランジションあり。

トランジションはあったほうがいいですね。

やっぱり、Apple 公式サンプルコードは偉大。



【Apple WWDC24】Swift ネタをサンプルコードとともに眺めていくページ

いよいよです。



👉 WWDC24 - Apple Developer hatena-bookmark

Apple 公式の GitHub では、

「sample」

の prefix をつけてリポジトリを公開していますよね。

洗練されていて、Swift の方向性も示されてるようで。

👉 Repository search results hatena-bookmark

いや、もしかしたら、GitHub 公開は遅れるかもしれん。

(更新中 ...)



【SwiftUI】ScrollView や List を snap する


作ってみると、何かがきもい選択肢リストの挙動。

上下の padding 付近が気になります。

 

🧑🏻‍💻 snap する

スクロールしたときの

選択肢のアイテムを

きりのいいところで止まるようにします。

ScrollView を使ったリストの実装に、

.scrollTargetLayout()

.scrollTargetBehavior(.viewAligned)

の2行を追加するだけできっちり止まるようになります。

👉 ScrollTargetBehavior | Apple Developer Documentation hatena-bookmark



計算とかしなくていいです。

便利。

ページングもできるとかすげえ。

👉 [WWDC2023] iOS17におけるScrollViewの新機能  その1 hatena-bookmark
👉 UICollectionView with Snapping and Scaling in Swift | by Satsuki Hashiba | Medium hatena-bookmark

 

🧑🏻‍💻 結果

ScrollView 上下のきわきわがすっきりしました !

しかし、「snap」て難しい英単語ですね。

👉 snapの意味・使い方・読み方|英辞郎 on the WEB hatena-bookmark

「スナップエンドウ」てやつ、

前から気にはなってました。


将来、URL の twitter.com は x.com となるんだろうか。

アイコンが変わりました。

URLはどうなるのでしょうか。


❯ curl -I https://x.com
HTTP/2 302
date: Mon, 24 Jul 2023 14:24:27 GMT
location: https://twitter.com/
cache-control: private, max-age=0, no-store, no-cache, must-revalidate, post-check=0, pre-check=0
expires: Thu, 01 Jan 1970 00:00:01 GMT
server: cloudflare
cf-ray: 7ebcd3ab8e352615-NRT

❯ curl -I https://twitter.com
HTTP/2 403
date: Mon, 24 Jul 2023 14:24:21 GMT
perf: 7626143928
server: tsa_m
set-cookie: guest_id_marketing=v1%3A169020866196904294; Max-Age=63072000; Expires=Wed, 23 Jul 2025 14:24:21 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
set-cookie: guest_id_ads=v1%3A169020866196904294; Max-Age=63072000; Expires=Wed, 23 Jul 2025 14:24:21 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
set-cookie: personalization_id="v1_oj788V5nRvbYdR1OvohwoQ=="; Max-Age=63072000; Expires=Wed, 23 Jul 2025 14:24:21 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
set-cookie: guest_id=v1%3A169020866196904294; Max-Age=63072000; Expires=Wed, 23 Jul 2025 14:24:21 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
x-powered-by: Express
cache-control: no-cache, no-store, max-age=0
x-transaction-id: dd0d24c26c46ed06
strict-transport-security: max-age=631138519
x-response-time: 182
x-connection-hash: 0a63336cc2c8ce1c490be21f121a4f8e8442c7a69dc1ee67c226dc672635b233

これは、どう考えるべきか。

完全移行しますかね。

しれっと、Unicode 文字も存在する。



【無料】誰でも作れる Animated Drawings で手書き静止画が動き始める件

まず、絵を描きます。

以下からアップロードします。

👉 Animated Drawings hatena-bookmark

「NEXT」を押して進んでいきます。途中で、アクションを選んだり、簡単な調整ができます。

こんなのできました。



素晴らしすぎます。ほとんど絵を書いてアップロードするだけです。


👉 FAIR Animated Drawings: Home hatena-bookmark

Python です。GitHub で公開されています。

👉 facebookresearch/AnimatedDrawings: Code to accompany "A Method for Animating Children's Drawings of the Human Figure" hatena-bookmark