Compose 中的可见性跟踪

跟踪界面元素何时在屏幕上显示对于各种使用情形都很有用,例如记录分析数据、管理界面状态,以及通过自动播放或暂停视频内容来优化资源。Compose 提供了多个用于跟踪界面元素可见性的修饰符,例如:

  • 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.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 Bot。在图 2 中,由于可组合项未完全显示,因此第三个聊天机器人未加载。在图 3 中,minFractionVisible 已设置,第三个机器人会在完全显示在屏幕上之前加载。