在 Compose 中追蹤曝光率

追蹤 UI 元素在畫面上顯示的時間,有助於處理各種用途,例如記錄 Analytics、管理 UI 狀態,以及自動播放或暫停影片內容,藉此最佳化資源。Compose 提供多種修飾符,可追蹤 UI 元素的可見度,例如:

  • onVisibilityChanged - 這個修飾符會在可組合函式的顯示狀態變更時通知您。每當可組合項顯示時,這項函式就會觸發動作或副作用,非常適合用於這類情況。
  • onLayoutRectChanged - 這個修飾符會提供可組合函式相對於根、視窗和螢幕的邊界資訊。這個 API 提供低層級控制項,也是 onVisibilityChanged 的基礎 API。這個修飾符與 onGloballyPositioned 類似,但效能更佳,彈性也更高。

您可以在修飾符鏈結中,將這些 API 與任何可組合函式搭配使用。

使用 onVisibilityChanged 追蹤顯示設定變更

瞭解項目何時對使用者顯示或部分顯示,有助於追蹤 Analytics (例如觀看人數)、提升效能 (僅在項目顯示時從網路擷取或預先擷取資料),甚至觸發事件 (播放或暫停影片)。

如要在項目可見度變更時收到通知,請使用 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.0f1.0f 的浮點值,預設為 1.0f1.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 中,minFractionVisible 已設定,第三個機器人會在完全顯示於畫面上之前載入。