Modificadores de rolagem
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 fundamental 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
do delta de gestos, corte de conteúdo e efeitos de rolagem excessiva.
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é semanticamente invertido para representar a mudança selecionada na posição de rolagem e fazer com 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 em como o conteúdo deve 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 a |
delta informado a |
|---|---|---|
O ponteiro se move para CIMA |
Negativa |
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: indica se a direção da rolagem está invertida.
Além de inverter o delta de rolagem, scrollableArea também corta o conteúdo nos limites do layout e processa a renderização de efeitos de rolagem excessiva. Por padrão, ele usa o efeito fornecido por LocalOverscrollFactory.
Para personalizar ou desativar isso, use 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 layouts Lazy. 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: aplicar transformações, dimensionamento ou outros efeitos às crianças enquanto elas rolam a tela.
- Controle direto: necessidade de controle refinado sobre a mecânica de rolagem
além do que
verticalScrollou layouts Lazy expõem.
Crie listas personalizadas semelhantes a rodas usando scrollableArea
O exemplo a seguir demonstra o uso de scrollableArea para criar uma lista vertical personalizada em que os itens diminuem à medida que se afastam do centro, criando um efeito visual semelhante a uma 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, a delegação é feita ao usuário por
ScrollableState
, que é necessário para que esse modificador funcione corretamente.
Ao criar ScrollableState, é necessário fornecer uma função consumeScrollDelta
que 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.
- Entender os gestos
- Migrar
CoordinatorLayoutpara o Compose - Como usar visualizações no Compose