Os modificadores
verticalScroll
e
horizontalScroll
oferecem a forma mais simples de permitir que o usuário role um elemento quando
os limites do conteúdo são maiores que as restrições de tamanho máximo. Com
os modificadores verticalScroll e horizontalScroll, não é necessário
transladar nem deslocar o conteúdo.
@Composable private fun ScrollBoxes() { Column( modifier = Modifier .background(Color.LightGray) .size(100.dp) .verticalScroll(rememberScrollState()) ) { repeat(10) { Text("Item $it", modifier = Modifier.padding(2.dp)) } } }
O ScrollState
permite mudar a posição de rolagem ou descobrir o estado atual. Para criá-lo
com parâmetros padrão, use
rememberScrollState().
@Composable private fun ScrollBoxesSmooth() { // Smoothly scroll 100px on first composition val state = rememberScrollState() LaunchedEffect(Unit) { state.animateScrollTo(100) } Column( modifier = Modifier .background(Color.LightGray) .size(100.dp) .padding(horizontal = 8.dp) .verticalScroll(state) ) { repeat(10) { Text("Item $it", modifier = Modifier.padding(2.dp)) } } }
Modificador de área rolável
O modificador scrollableArea é um elemento básico para criar
contêineres roláveis personalizados. Ele oferece uma abstração de nível mais alto sobre o modificador
scrollable, processando requisitos comuns, como interpretação de delta de gesto, recorte de conteúdo e efeitos de rolagem esticada.
Embora scrollableArea seja usado para implementações personalizadas, geralmente é melhor
preferir soluções prontas, como verticalScroll, horizontalScroll
ou elementos combináveis, como LazyColumn, para listas de rolagem padrão. Esses
componentes de nível mais alto são mais simples para casos de uso comuns e são criados
usando scrollableArea.
Diferença entre os modificadores scrollableArea e scrollable
A principal diferença entre scrollableArea e scrollable está na forma como eles
interpretam os gestos de rolagem do usuário:
scrollable(delta bruto): o delta reflete diretamente o movimento físico da entrada do usuário (por exemplo, arrastar o ponteiro) na tela.scrollableArea(delta orientado ao conteúdo): odeltaé invertido semanticamente para representar a mudança selecionada na posição de rolagem para que o conteúdo pareça se mover com o gesto do usuário, que geralmente é o oposto do movimento do ponteiro.
Pense assim: scrollable informa como o ponteiro se moveu, enquanto
scrollableArea traduz esse movimento do ponteiro em como o conteúdo precisa
se mover em uma visualização rolável típica. Essa inversão é o motivo pelo qual scrollableArea
parece mais natural ao implementar um contêiner rolável padrão.
A tabela a seguir resume os sinais de delta para cenários comuns:
Interação inicial |
delta informado para |
delta informado para |
|---|---|---|
O ponteiro se move PARA CIMA |
Negativo |
Positivo |
O ponteiro se move para BAIXO |
Positivo |
Negativo |
O ponteiro se move para a ESQUERDA |
Negativo |
Positivo (negativo para RTL) |
O ponteiro se move para a DIREITA |
Positivo |
Negativo (positivo para RTL) |
(*) Observação sobre o sinal delta de scrollableArea: o sinal do delta de scrollableArea não é apenas uma inversão simples. Ele considera de forma inteligente:
- Orientação: vertical ou horizontal.
LayoutDirection: LTR ou RTL (especialmente importante para rolagem horizontal).- Flag
reverseScrolling: se a direção de rolagem está invertida.
Além de inverter o delta de rolagem, o scrollableArea também corta o
conteúdo para os limites do layout e processa a renderização de efeitos de
rolagem esticada. Por padrão, ele usa o efeito fornecido por LocalOverscrollFactory.
É possível personalizar ou desativar esse recurso usando a sobrecarga scrollableArea,
que aceita um parâmetro OverscrollEffect.
Quando usar o modificador scrollableArea
Use o modificador scrollableArea quando precisar criar um componente de rolagem
personalizado que não seja atendido adequadamente pelos modificadores horizontalScroll ou
verticalScroll ou por layouts lentos. Isso geralmente envolve casos com:
- Lógica de layout personalizada: quando a disposição dos itens muda dinamicamente com base na posição de rolagem.
- Efeitos visuais exclusivos: aplicação de transformações, dimensionamento ou outros efeitos aos filhos enquanto eles rolam.
- Controle direto: quando você precisa de um controle detalhado sobre a mecânica de rolagem
além do que o
verticalScrollou os layouts lentos expõem.
Criar listas personalizadas em formato de roda usando scrollableArea
O exemplo a seguir demonstra o uso de scrollableArea para criar uma lista vertical personalizada em que os itens são reduzidos verticalmente à medida que se afastam do centro, criando um efeito visual de "roda". Esse tipo de transformação dependente de rolagem é um
caso de uso perfeito para scrollableArea.
scrollableArea.
@Composable private fun ScrollableAreaSample() { // ... Layout( modifier = Modifier .size(150.dp) .scrollableArea(scrollState, Orientation.Vertical) .background(Color.LightGray), // ... ) { measurables, constraints -> // ... // Update the maximum scroll value to not scroll beyond limits and stop when scroll // reaches the end. scrollState.maxValue = (totalHeight - viewportHeight).coerceAtLeast(0) // Position the children within the layout. layout(constraints.maxWidth, viewportHeight) { // The current vertical scroll position, in pixels. val scrollY = scrollState.value val viewportCenterY = scrollY + viewportHeight / 2 var placeableLayoutPositionY = 0 placeables.forEach { placeable -> // This sample applies a scaling effect to items based on their distance // from the center, creating a wheel-like effect. // ... // Place the item horizontally centered with a layer transformation for // scaling to achieve wheel-like effect. placeable.placeRelativeWithLayer( x = constraints.maxWidth / 2 - placeable.width / 2, // Offset y by the scroll position to make placeable visible in the viewport. y = placeableLayoutPositionY - scrollY, ) { scaleX = scaleFactor scaleY = scaleFactor } // Move to the next item's vertical position. placeableLayoutPositionY += placeable.height } } } } // ...
Modificador scrollable
O modificador
scrollable
é diferente dos modificadores de rolagem, porque scrollable detecta os
gestos de rolagem e captura os deltas, mas não desloca o conteúdo
automaticamente. Em vez disso, isso é delegado ao usuário por meio de
ScrollableState,
que é necessário para que esse modificador funcione corretamente.
Ao criar ScrollableState, é necessário fornecer uma função consumeScrollDelta,
que vai ser invocada em cada etapa de rolagem (por entrada de gestos, rolagem
suave ou deslizamento rápido) com o delta em pixels. Essa função precisa retornar a
quantidade de distância de rolagem consumida. Isso é para garantir que o evento seja propagado
corretamente nos casos em que há elementos aninhados com o modificador
scrollable.
O snippet a seguir detecta os gestos e exibe um valor numérico para o deslocamento, mas não desloca os elementos:
@Composable private fun ScrollableSample() { // actual composable state var offset by remember { mutableFloatStateOf(0f) } Box( Modifier .size(150.dp) .scrollable( orientation = Orientation.Vertical, // Scrollable state: describes how to consume // scrolling delta and update offset state = rememberScrollableState { delta -> offset += delta delta } ) .background(Color.LightGray), contentAlignment = Alignment.Center ) { Text(offset.toString()) } }
Recomendados para você
- Observação: o texto do link aparece quando o JavaScript está desativado.
- Noções básicas sobre gestos
- Migrar
CoordinatorLayoutpara o Compose - Como usar visualizações no Compose