Rastreamento de visibilidade no Compose

Saber quando um elemento da interface está visível na tela é útil para vários casos de uso, como registrar análises, gerenciar o estado da interface e otimizar recursos ao reproduzir ou pausar automaticamente o conteúdo de vídeo. O Compose oferece vários modificadores para rastrear a visibilidade de elementos da interface, como:

  • onVisibilityChanged: esse modificador notifica você quando a visibilidade de um elemento combinável muda. É ideal para acionar uma ação ou um efeito colateral sempre que o elemento que pode ser composto ficar visível.
  • onLayoutRectChanged: esse modificador fornece informações sobre os limites de um elemento combinável em relação à raiz, à janela e à tela. Ela oferece controle de baixo nível e é a API de base para onVisibilityChanged. O modificador é semelhante a onGloballyPositioned, mas oferece melhor desempenho e maior flexibilidade.

É possível usar essas APIs com qualquer elemento combinável como parte da cadeia de modificadores.

Monitorar mudanças de visibilidade com onVisibilityChanged

Saber quando um item está visível ou parcialmente visível para um usuário pode ajudar a acompanhar análises (por exemplo, contagem de visualizações), otimizar o desempenho (buscando ou pré-buscando dados da rede somente quando o item está visível) ou até mesmo acionar eventos (reproduzir ou pausar vídeos).

Para receber uma notificação quando a visibilidade de um item mudar, use o modificador onVisibilityChanged, como mostrado no exemplo a seguir:

Text(
    text = "Some text",
    modifier = Modifier
        .onVisibilityChanged { visible ->
            if (visible) {
                // Do something if visible.
            } else {
                // Do something if not visible.
            }
        }
        .padding(vertical = 8.dp)
)

O modificador onVisibilityChanged fornece um valor booleano que reflete o estado de visibilidade atual do elemento combinável. Além disso, ele oferece parâmetros como minFraction e minDurationMs, que dão mais controle sobre quando o callback de visibilidade precisa ser acionado.

Como em qualquer outro modificador, a sequência é importante com o modificador onVisibilityChanged. O exemplo anterior mostra uma função combinável que renderiza texto com padding. Para garantir que o modificador afete todo o elemento combinável, incluindo o padding, adicione o modificador onVisibilityChanged antes do padding.

Definir um limite de tempo em um elemento combinável antes de acionar o callback de visibilidade

Em algumas situações, talvez você queira acionar uma ação somente depois que um item estiver visível para o usuário por um determinado período. Por exemplo, é possível reproduzir automaticamente um vídeo se ele estiver visível para o usuário há algum tempo.

Para acionar uma ação depois que um item ficar visível por um período definido, use o parâmetro minDurationMs no modificador onVisibilityChanged. Esse parâmetro especifica o tempo mínimo que um elemento combinável precisa ficar continuamente visível para que o callback seja acionado. Se o elemento combinável deixar de ficar visível antes que a duração seja atingida, o timer será redefinido. O valor padrão é 0 milissegundo.

O snippet abaixo muda o plano de fundo para roxo depois que o elemento que pode ser composto fica visível para o usuário por três segundos:

var background by remember { mutableStateOf(PalePink) }
Card(
    modifier = modifier
        // ...
        .onVisibilityChanged(minDurationMs = 3000) {
            if (it) {
                background = MutedPlum
            }
        }
) {

    Box(
        modifier = Modifier
            // ...
            .background(background),
        contentAlignment = Alignment.Center,
    ) {
        // ...
    }
}

Figura 1. O plano de fundo muda de rosa para ameixa depois que o elemento combinável fica na tela por três segundos contínuos.

Definir uma fração visível mínima

Definir uma fração mínima visível para o callback de visibilidade do elemento combinável é útil ao trabalhar com conteúdo rolável (por exemplo, LazyColumn) para otimizar a busca de dados de itens que excedem o tamanho da tela.

Nesses casos, use o parâmetro minFractionVisible no modificador onVisibilityChanged para definir a fração que precisa estar na tela para que o elemento combinável seja marcado como visível. Ele aceita valores flutuantes de 0.0f a 1.0f e é definido como 1.0f por padrão. 1.0f significa que o elemento combinável precisa estar completamente visível na tela para que o callback seja acionado.

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)
            )
        }
    }
}

Figura 2. Sem que minFractionVisible seja definido. Figura 3. Com minFractionVisible definido como 0.2f.

O exemplo usado anteriormente pré-carrega os Androidify Bots da rede antes que o elemento combinável fique completamente visível. Na Figura 2, o terceiro bot não é carregado, porque o elemento combinável não está totalmente visível. Na Figura 3, minFractionVisible está definido, e o terceiro bot é carregado antes de ficar totalmente visível na tela.