Отслеживание видимости в Compose

Отслеживание видимости элемента пользовательского интерфейса на экране полезно для различных задач, таких как ведение аналитики, управление состоянием интерфейса и оптимизация ресурсов путем автоматического воспроизведения или приостановки видеоконтента. Compose предлагает несколько модификаторов для отслеживания видимости элементов пользовательского интерфейса, например:

  • onVisibilityChanged — этот модификатор уведомляет вас об изменении видимости составного элемента. Он идеально подходит для запуска действия или побочного эффекта каждый раз, когда составной элемент становится видимым.
  • onLayoutRectChanged — этот модификатор предоставляет информацию о границах составного элемента относительно корневого элемента, окна и экрана. Он обеспечивает низкоуровневое управление и является базовым API для onVisibilityChanged . Модификатор похож на 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 . В приведенном выше примере показана составная функция, которая отображает текст с отступами. Чтобы убедиться, что модификатор влияет на всю составную функцию вместе с отступами, добавьте модификатор onVisibilityChanged перед модификатором padding .

Установите временной лимит для составного объекта перед запуском обратного вызова для проверки видимости.

В некоторых ситуациях может потребоваться запустить действие только после того, как элемент будет виден пользователю в течение определенного времени. Например, можно автоматически воспроизвести видео, если оно было видно пользователю в течение некоторого времени.

Чтобы запустить действие после того, как элемент будет виден в течение заданного периода времени, используйте параметр minDurationMs в модификаторе onVisibilityChanged . Этот параметр задает минимальное время, в течение которого составной объект должен оставаться видимым, чтобы сработала функция обратного вызова. Если составной объект перестает быть видимым до истечения заданного времени, таймер сбрасывается. Значение по умолчанию — 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 ) для оптимизации получения данных для элементов, превышающих размер экрана.

В таких случаях используйте параметр minFractionVisible в модификаторе onVisibilityChanged , чтобы определить долю экрана, необходимую для того, чтобы компонент был помечен как видимый. Он поддерживает значения с плавающей запятой от 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 установлено значение minFractionVisible , и третий бот загружается до того, как он станет полностью видимым на экране.