はじめに
パスワードの入力欄でよくあるのが、間違ったパスワードを入力すると入力欄がシェイク(ブルブル)して間違っていることを知らせるといったUIです。
これをiOS17から登場したkeyframeAnimator
を使って実装してみたいと思います。
keyframeAnimator
を使用せず、実装したい場合は以下の記事が参考になると思います。
サンプルアプリ
キーボードでreturnを押すと、テキストフィールドがシェイクします。
間違ったものを入力していたという想定です。
実装
import SwiftUI
struct KeyframeAnimationValues {
var offsetX = 0.0
}
struct ContentView: View {
@State private var text = ""
@State private var shakeAnimationTrigger = false
var body: some View {
VStack {
TextField("文字を入力してください", text: $text)
.textFieldStyle(.roundedBorder)
.keyframeAnimator(
initialValue: KeyframeAnimationValues(),
trigger: shakeAnimationTrigger
) { content, value in
content.offset(x: value.offsetX)
} keyframes: { _ in
KeyframeTrack(\.offsetX) {
CubicKeyframe(5, duration: 0.2)
CubicKeyframe(-5, duration: 0.1)
CubicKeyframe(5, duration: 0.1)
CubicKeyframe(-5, duration: 0.1)
CubicKeyframe(5, duration: 0.1)
CubicKeyframe(0, duration: 0.2)
}
}
.onSubmit {
shakeAnimationTrigger.toggle()
}
}
.padding(20)
}
}
解説
アニメーションで必要な値を構造体で定義します。
今回はoffsetのxをいじりたいのでoffsetX
を定義します。
struct KeyframeAnimationValues {
var offsetX = 0.0
}
アニメーションのトリガーを定義します。
@State private var shakeAnimationTrigger = false
initialValue
には先ほど作成した構造体を初期化して渡します。
trigger
に先ほど定義したトリガーを渡します。
keyframes
で継続時間と値をセットで渡します。
keyframes
で設定した値がvalue
として流れてくるので、content.offset(x:)
でvalue.offsetX
を設定します。
.keyframeAnimator(
initialValue: KeyframeAnimationValues(),
trigger: shakeAnimationTrigger
) { content, value in
content.offset(x: value.offsetX)
} keyframes: { _ in
KeyframeTrack(\.offsetX) {
CubicKeyframe(5, duration: 0.2)
CubicKeyframe(-5, duration: 0.1)
CubicKeyframe(5, duration: 0.1)
CubicKeyframe(-5, duration: 0.1)
CubicKeyframe(5, duration: 0.1)
CubicKeyframe(0, duration: 0.2)
}
}
今回はonSubmit
で毎回シェイクされるようにshakeAnimationTrigger
をtoggle()
します。
shakeAnimationTrigger = true
のようにすると値がfalse
に戻らないので正常に動作しません。
.onSubmit {
shakeAnimationTrigger.toggle()
}
おわり
KeyframeAnimationについて以前書いた記事はこちらです。
KeyframeAnimationがあると色んなアニメーションが作れて楽しいです