[SwiftUI]Gesture Stateやupdatingとか
Appleの公式をDeepLで翻訳しつつ、ちょっとわかり辛いところは内容を補完してます。
公式の内容
ユーザーがジェスチャーを行っている間、プロパティを更新し、ジェスチャーが終了するとプロパティを初期状態に戻すプロパティラッパータイプです。
@propertyWrapper @frozen struct GestureState<Value>
プロパティを @GestureState として宣言し、ジェスチャーの update(_:body:) コールバックのパラメータとしてそのバインディングを渡し、その更新を受け取ります。GestureState として宣言されたプロパティは、ジェスチャが非アクティブになると暗黙的にリセットされるので、過渡的な状態を追跡するのに適しています。
プロパティを @GestureState として宣言することで、長押しジェスチャを Circle に追加し、ジェスチャ中にインターフェースを更新することができます。
struct SimpleLongPressGestureView: View {
@GestureState var isDetectingLongPress = false
var longPress: some Gesture {
LongPressGesture(minimumDuration: 3)
.updating($isDetectingLongPress) { currentState, gestureState, transaction in
gestureState = currentState
}
}
var body: some View {
Circle()
.fill(self.isDetectingLongPress ? Color.red : Color.green)
.frame(width: 100, height: 100, alignment: .center)
.gesture(longPress)
}
}
何もしていない時は、円が緑色です。
タップすると縁が赤色になります。タップした状態を維持していても3秒経つとまた緑に戻ります。
updatingについて
定義は以下
@inlinable public func updating<State>(_ state: GestureState<State>, body: @escaping (Self.Value, inout State, inout Transaction) -> Void) -> GestureStateGesture<Self, State>
ジェスチャーの値の変更に伴い、提供されたジェスチャーの状態プロパティを更新します。
このコールバックを使用して、一時的な UI 状態を更新します。
パラメータ
state – ビューの GestureState プロパティへのバインディング。
body – ジェスチャの値が変更されたときに SwiftUI が呼び出すコールバック。その currentState
パラメータは、更新されたジェスチャーを作成します。gestureStateパラメータは、以前のジェスチャーの状態を表します。 transactionはジェスチャーのコンテキストを表します。
戻り値
元のジェスチャーの値が変わると提供された状態を更新し、ユーザーがジェスチャーをキャンセルまたは終了すると状態を初期値にリセットします。
内容の補完と理解
これ実際にソースコードをコピペして動かしてみないと多少誤解しそうだ。
実際に動かしてみて分かったこと
・minimumDurationは秒で、タップしてから3秒で円の色は変化する。
・updating処理はタップした瞬間に発生する。持続的に呼ばれるわけではなく、タップした一度のみ。(一度のみと言ってますが、リセット後にもう一度タップすると呼ばれた。)
・gestureStateとcurrentState
の型はGestureのタイプによって変化する。
・gestureState = currentState
をコメントアウトすると色が変わらなくなる。
updating処理でブレーク止めてみると、それぞれ以下のような値を保持していることがわかった。
ただ、transactionはジェスチャーのコンテキストが入ってくるとのことでしたが、空の配列を保持しているだけでした。
MagnificationGestureのサンプル
こちらのサンプルでもGestureStateが使われていて、使い方としては似ている。
gestureState = currentStateも同じだ。transactionはどのタイミングで使うのかはよくわからない。
struct MagnificationGestureView: View {
@GestureState var magnifyBy = 1.0
var magnification: some Gesture {
MagnificationGesture()
.updating($magnifyBy) { currentState, gestureState, transaction in
gestureState = currentState
}
}
var body: some View {
Circle()
.frame(width: 100, height: 100)
.scaleEffect(magnifyBy)
.gesture(magnification)
}
}
実際にコードを実行してみると、gestureStategestureStateとcurrentStateが Dobuleになっていた。
イベントごとにgestureStateの型は変化するようです。
ディスカッション
コメント一覧
まだ、コメントがありません