Rastreamento de visibilidade no Compose

O acompanhamento da visibilidade de um elemento da interface na tela é útil para vários casos de uso, como registro de análises, gerenciamento do estado da interface e otimização de recursos reproduzindo ou pausando automaticamente o conteúdo de vídeo. O Compose oferece vários modificadores para acompanhar a visibilidade de elementos da interface, como:

  • onVisibilityChanged: esse modificador notifica quando a visibilidade de um elemento combinável muda. Ele é ideal para acionar uma ação ou efeito colateral sempre que o elemento combinável fica visível.
  • onLayoutRectChanged: esse modificador fornece informações sobre os limites de um elemento combinável em relação à raiz, à janela e à tela. Ele 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.

Você pode usar essas APIs com qualquer elemento combinável como parte da cadeia de modificadores.

Acompanhar mudanças de visibilidade com onVisibilityChanged

Entender quando um item está visível ou parcialmente visível para um usuário pode ajudar a acompanhar análises (por exemplo, contagem de espectadores), otimizar o desempenho (buscar ou buscar dados da rede apenas quando o item estiver 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, conforme 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 oferecem um controle mais refinado sobre quando o callback de visibilidade precisa ser acionado.

Como todos os outros modificadores, a sequenciação é 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 junto com o padding, adicione o modificador onVisibilityChanged antes do modificador 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, você pode reproduzir um vídeo automaticamente se ele estiver visível para o usuário por algum tempo.

Para acionar uma ação depois que um item estiver visível por um período definido, use o parâmetro minDurationMs no modificador onVisibilityChanged. Esse parâmetro especifica o período mínimo de tempo que um elemento combinável precisa estar visível continuamente 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 milissegundos.

O snippet a seguir muda o plano de fundo para roxo depois que o elemento combinável fica visível para o usuário por 3 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 3 segundos continuamente.

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

Definir uma fração visível mínima 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 para 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 oferece suporte a valores flutuantes que variam de 0.0f a 1.0f e é definido como 1.0f por padrão. 1.0f significa que o elemento combinável precisa estar totalmente visível na tela para que o callback seja acionado.

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

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

O exemplo usado anteriormente pré-carrega os bots do Androidify da rede antes que o elemento combinável fique totalmente 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.