Compose での可視性トラッキング

UI 要素が画面に表示されるタイミングをトラッキングすることは、分析のロギング、UI 状態の管理、動画コンテンツの自動再生または一時停止によるリソースの最適化など、さまざまなユースケースで役立ちます。Compose には、UI 要素の可視性を追跡するための修飾子がいくつか用意されています。

  • onVisibilityChanged - この修飾子は、コンポーザブルの公開設定が変更されたときに通知します。コンポーザブルが表示されるたびにアクションまたは副作用をトリガーするのに最適です。
  • onLayoutRectChanged - この修飾子は、ルート、ウィンドウ、画面を基準としたコンポーザブルの境界に関する情報を提供します。低レベルの制御を提供し、onVisibilityChanged の基盤となる API です。この修飾子は onGloballyPositioned に似ていますが、パフォーマンスが向上し、柔軟性が高まります。

これらの API は、修飾子チェーンの一部として任意のコンポーザブルで使用できます。

onVisibilityChanged で公開設定の変更を追跡する

アイテムがユーザーに表示されているか、部分的に表示されているかを把握することで、分析の追跡(視聴回数など)、パフォーマンスの最適化(アイテムが表示されている場合にのみネットワークからデータを取得またはプリフェッチする)、イベントのトリガー(動画の再生または一時停止)に役立ちます。

アイテムの可視性が変更されたときに通知を受け取るには、次の例に示すように onVisibilityChanged 修飾子を使用します。

Text(
    text = "Some text",
    modifier = Modifier
        .onVisibilityChanged { visible ->
            if (visible) {
                // Do something if visible
            } else {
                // Do something if not visible
            }
        }
        .padding(vertical = 8.dp)
)

onVisibilityChanged 修飾子は、コンポーザブルの現在の可視性の状態を反映するブール値を返します。また、minFraction や minDurationMs などのパラメータを使用すると、可視性コールバックをトリガーするタイミングをより細かく制御できます。

他の修飾子と同様に、onVisibilityChanged 修飾子でも順序が重要です。上記の例は、パディング付きのテキストをレンダリングするコンポーズ可能な関数を示しています。修飾子がパディングとともにコンポーザブル全体に影響するようにするには、padding 修飾子の前に onVisibilityChanged 修飾子を追加します。

視認性コールバックをトリガーする前に、コンポーザブルに制限時間を設定する

場合によっては、アイテムが一定時間ユーザーに表示された後にのみアクションをトリガーしたいことがあります。たとえば、動画がユーザーに一定時間表示されている場合に、動画を自動再生できます。

アイテムが一定期間表示された後にアクションをトリガーするには、onVisibilityChanged 修飾子の minDurationMs パラメータを使用します。このパラメータは、コールバックがトリガーされるためにコンポーザブルが継続的に表示される必要がある最小時間を指定します。期間が経過する前にコンポーザブルが表示されなくなった場合、タイマーはリセットされます。デフォルト値は 0 ミリ秒です。

次のスニペットは、コンポーザブルがユーザーに 3 秒間表示された後、背景を紫色に変更します。

var background by remember { mutableStateOf(PalePink) }
Card(
    modifier = modifier
        // ...
        .onVisibilityChanged(minDurationMs = 3000) {
            if (it) {
                background = MutedPlum
            }
        }
) {

    Box(
        modifier = Modifier
            // ...
            .background(background),
        contentAlignment = Alignment.Center,
    ) {
        // ...
    }
}

図 1. コンポーザブルが画面に 3 秒間連続して表示されると、背景がピンクからプラムに変わります。

表示される最小割合を設定する

コンポーザブルの可視性コールバックに最小可視部分を設定すると、スクロール可能なコンテンツ(LazyColumn など)を操作する際に、画面サイズを超えるアイテムのデータ取得を最適化できます。

このような場合は、onVisibilityChanged 修飾子の minFractionVisible パラメータを使用して、コンポーザブルが表示可能としてマークされるために画面に表示される必要がある割合を定義します。0.0f から 1.0f までの浮動小数点値をサポートし、デフォルトでは 1.0f に設定されています。1.0f は、コールバックがトリガーされるために、コンポーザブルが画面に完全に表示される必要があることを意味します。

LazyColumn(
    modifier = modifier.fillMaxSize()
) {
    item {
        Box(
            modifier = Modifier
                // ...
                // Here the visible callback gets triggered when 20% of the composable is visible
                .onVisibilityChanged(
                    minFractionVisible = 0.2f,
                ) { visible ->
                    if (visible) {
                        // Call specific logic here
                        // viewModel.fetchDataFromNetwork()
                    }
                }
                .padding(vertical = 16.dp)
        ) {
            Text(
                text = "Sample Text",
                modifier = Modifier.padding(horizontal = 16.dp)
            )
        }
    }
}

図 2. minFractionVisible が設定されていない場合。 図 3. minFractionVisible を 0.2f に設定。

前述の例では、コンポーザブルが完全に表示される前に、ネットワークから Androidify ボットをプリロードしています。図 2 では、コンポーザブルが完全に表示されていないため、3 番目の bot は読み込まれません。図 3 では、minFractionVisible が設定されており、3 番目のボットが画面に完全に表示される前に読み込まれます。