在 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 修飾符會提供布林值,反映可組合項目前的顯示狀態。此外,這個 API 還提供 minFractionVisible 和 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 表示可組合項必須完全顯示在畫面上,或填滿整個可視區域 (如果可組合項大於可視區域)。

當可見部分大於 minFractionVisible,或可組合項完全可見或填滿可視區域時,回呼會收到 true。否則會收到 false。

LazyColumn(
    modifier = modifier.fillMaxSize()
) {
    item {
        Box(
            modifier = Modifier
                // ...
                // Here `visible` is `true` when more than 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 已設定,第三個機器人會在完全顯示在畫面上之前載入。

隱藏可組合項並保留其空間

如要隱藏可組合項,而不變更周圍的版面配置,請使用 visible 修飾符。傳遞 false 時,系統仍會測量可組合項,但不會放置或繪製。與將 alpha 設為 0f 不同,visible(false) 也會從無障礙樹狀結構中移除元素,並停用觸控互動,同時保留其版面配置空間。

以下範例顯示勾號圖示在隱藏時仍保留空間,因此旁邊的文字不會移動:

Row(modifier, verticalAlignment = Alignment.CenterVertically) {
    Icon(
        painter = painterResource(R.drawable.check),
        contentDescription = "Saved",
        modifier = Modifier
            // The icon keeps its space while it's hidden, so the text doesn't move.
            .visible(isSaved)
    )
    Text("Draft", Modifier.padding(start = 8.dp))
}

如果可組合項周圍的版面配置在可組合項出現和消失時不得移動,請使用 visible。如要移除可組合項及其空間,請不要呼叫該可組合項,或使用 AnimatedVisibility 建立淡入和淡出動畫。