Yappli Tech Blog

株式会社ヤプリの開発メンバーによるブログです。最新の技術情報からチーム・働き方に関するテーマまで、日々の熱い想いを持って発信していきます。

Composeで拡大縮小ジェスチャー終わりを検知する方法

こんにちは、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)
) {
    // 表示・ジェスチャーの対象コンテンツ
}

LaunchedEffectTransformableStateisTransformInProgressを使うことで、簡単に実装することができました 💯

TransformableStateで検知できるジェスチャー処理は全てこちらで対応できるので、二本指でのドラッグ移動などに対しても同じように実装することができます。

他のジェスチャー処理との併用について

Composeでジェスチャーを認識して処理をしたい時は Modifier.pointerInputModifier.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と仲良くしていきたいですね!

さいごに

ヤプリにご興味がある方いましたら是非カジュアル面談でヤプリ社員と話しませんか? 

open.talentio.com