Open3

Jetpack ComposeのGesture周りの関して

gottiegottie

https://engawapg.net/jetpack-compose/2404/pointerinput-and-gesture/

こちらの記事の下記のコードが全ての基本。
clickableなどComposeの操作関連は全て、pointerInputが使用されている。

Modifier.pointerInput(Unit) { // このスコープはPointerInputScope
    awaitEachGesture { //このスコープはAwaitPointerEventScope
        awaitFirstDown() // 最初のタッチダウンイベント
        do {
            val event = awaitPointerEvent() // イベントが発生
            // 個々のeventに対する処理
        } while (event.changes.fastAny { it.pressed }) // 一つでもタッチ継続中ならループ継続
    }
}
gottiegottie

ジェスチャーの伝搬について。
Composeではジェスチャーが子→親の順番で伝搬する。
つまり適切な伝搬のキャンセル処理を記述する必要がある。

val event = awaitPointerEvent().changes // PointerInputChange

PointerInputChangeは、「操作」に関しての情報がリストで入っている。例えば、画面のどこを触っているかなど。
PointerInputChangeはそのイベントが消費されているかどうか、を表すisConsumedというプロパティがあり、下記のようにconsume関数を呼び出して、消費したことを伝える。

event.changes.forEach {
    it.consume()
}
gottiegottie

consume()関数の説明には以下の記述がある。

Consumption" is just an indication of the claim and each pointer input handler implementation must manually check this flag to respect it.

つまりconsume()はただの消費されたことを表す主張であり、親側で正しくこのフラグを確認する必要がある。

つまり親側では、以下のようにキャンセルを考慮したコードを記述する必要がある。

.pointerInput(Unit) {
    awaitEachGesture {
        awaitFirstDown()
        do {
            val event = awaitPointerEvent()
            val canceled = event.changes.any { it.isConsumed }
            if (!canceled) {
     // キャンセルされていない場合は親側の処理が必要
            }
        } while (event.changes.any { it.pressed })
    }
}

ちなみに標準でPointerInputScopeに用意されている、detect~という関数は当然このキャンセルに対しての考慮があるが、自分でawaitEachGestureを使用すると、ここも考慮する必要がある