こんにちは、Androidエンジニアの 近藤(ふなち / Hunachi) です☺︎
私は最近業務でジェスチャー処理周りと格闘していました。
そこでとても小さめですがジェスチャー処理周りのTipsのうちの1つを共有したいと思います。
はじめに(今回実現したいこと)
今回実現したいことは、ユーザーによりコンテンツが元の1倍未満のサイズに縮小された時に、ユーザーが手を離したタイミングで元のサイズに戻すという処理です。
汎用的に言うと、Zoomや移動など、(2本指での)ジェスチャー処理終わりに何か処理をしたい ということです。
つまり、ジェスチャー処理の終わりを検知し、そこで好きな処理、今回だと元のサイズに戻す処理をすれば良さそうです。
解決方法
Modifier.transformable
を使って実装します。
var scale by rememberSaveable { mutableFloatStateOf(1f) } val transformableState = rememberTransformableState { zoomChange, _ , _ -> scale *= zoomChange } (transformableState.isTransformInProgress) { if (!transformableState.isTransformInProgress) { // ジェスチャー終わりにしたい処理をかく。 // 今回は指を離した時に、小さかったら戻す。 if (scale < 1f) { scale = 1f } } } Box( modifier = Modifier .fillMaxSize() .graphicsLayer { scaleX = scale scaleY = scale } .transformable(transformableState) ) { // 表示・ジェスチャーの対象コンテンツ }
LaunchedEffect
とTransformableState
のisTransformInProgress
を使うことで、簡単に実装することができました 💯
TransformableState
で検知できるジェスチャー処理は全てこちらで対応できるので、二本指でのドラッグ移動などに対しても同じように実装することができます。
他のジェスチャー処理との併用について
Composeでジェスチャーを認識して処理をしたい時は Modifier.pointerInput
や Modifier.transformable
を使うと思います。
pointerInput
の方が、色々なジェスチャーに対応していて便利なのですが、Zoomの終わりを認識したいのでisTransformInProgress
をデフォルトで実装してくれているtransformable
を使っています。
pointerInput
の機能(PointerInputScope
の拡張関数)を併用したい場合は、以下のように実装することができます。
val transformableState = rememberTransformableState { _, _, _ -> // ジェスチャー更新情報に対する処理 } LaunchedEffect(transformableState.isTransformInProgress) { if (!transformableState.isTransformInProgress) { // ジェスチャー終わりにしたい処理 } } Box( modifier = Modifier .graphicsLayer { // 見た目の更新の処理 } .pointerInput(Unit) { detectTapGestures( onDoubleTap = { offset -> // ダブルタップ時の処理 }, onTap = { // タップ時の処理 } ) } .transformable(transformableState) ) { // 表示・ジェスチャーの対象コンテンツ }
まとめ
今回は、 Composeで拡大縮小ジェスチャー終わりを検知する方法 を紹介しました。
Composeにはジェスチャー周りの便利な関数も色々実装されており大変ありがたいなぁと思う日々です 🌞
今後ももっとComposeと仲良くしていきたいですね!
さいごに
ヤプリにご興味がある方いましたら是非カジュアル面談でヤプリ社員と話しませんか?