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 修飾子は、コンポーザブルの現在の可視性の状態を反映するブール値を提供します。また、minFractionminDurationMs などのパラメータも用意されており、可視性コールバックをトリガーする必要があるタイミングをより細かく制御できます。

他のすべての修飾子と同様に、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. minFractionVisible0.2f に設定します。

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