No Compose, é possível encadear vários modificadores para mudar a aparência de um elemento combinável. Essas cadeias de modificadores podem afetar as restrições transmitidas aos elementos que podem ser compostos, que definem os limites de largura e altura.
Esta página descreve como os modificadores encadeados afetam as restrições e, consequentemente, a medição e o posicionamento de elementos combináveis.
Modificadores na árvore da IU
Para entender como os modificadores influenciam uns aos outros, é útil visualizar como eles aparecem na árvore da interface, que é gerada durante a fase de composição. Para mais informações, consulte a seção Composição.
Na árvore da interface, é possível visualizar os modificadores como nós de wrapper para os nós de layout:
Adicionar mais de um modificador a um elemento de composição cria uma cadeia de modificadores. Quando
você encadeia vários modificadores, cada nó de modificador envolve o restante da cadeia
e o nó de layout dentro dele. Por exemplo, quando você encadeia um modificador clip e um
size, o nó do modificador clip envolve o nó do modificador size,
que, por sua vez, envolve o nó de layout Image.
Na fase de layout, o algoritmo que percorre a árvore permanece o mesmo, mas cada nó modificador também é visitado. Dessa forma, um modificador pode mudar os requisitos de tamanho e o posicionamento do modificador ou do nó de layout que ele envolve.
Como mostrado na Figura 2, a implementação dos elementos combináveis Image e Text
consiste em uma cadeia de modificadores que envolvem um único nó de layout.
As implementações de Row e Column são nós de layout que descrevem como
organizar os filhos.
Para resumir:
- Os modificadores envolvem um único modificador ou nó de layout.
- Os nós de layout podem organizar vários nós filhos.
As seções a seguir descrevem como usar esse modelo mental para refletir sobre o encadeamento de modificadores e como isso influencia o tamanho dos elementos combináveis.
Restrições na fase de layout
A fase de layout segue um algoritmo de três etapas para encontrar a largura, a altura e as coordenadas x e y de cada nó de layout:
- Medir filhos: um nó mede os filhos, se houver.
- Decidir o próprio tamanho: com base nessas medições, um nó decide o próprio tamanho.
- Posicionar filhos: cada nó filho é posicionado em relação à própria posição de um nó.
Constraints ajudam a encontrar os tamanhos certos para os nós durante as duas primeiras etapas do algoritmo. As restrições definem os limites mínimo e máximo para a
largura e a altura de um nó. Quando o nó decide o tamanho, o tamanho medido
precisa estar dentro desse intervalo.
Tipos de restrições
Uma restrição pode ser uma das seguintes:
- Bounded: o nó tem uma largura e altura máximas e mínimas.
- Sem limite: o nó não tem restrição de tamanho. Os limites máximos de largura e altura são definidos como infinito.
- Exato: o nó precisa seguir um requisito de tamanho exato. Os limites mínimo e máximo são definidos com o mesmo valor.
- Combinação: o nó segue uma combinação dos tipos de restrição anteriores. Por exemplo, uma restrição pode limitar a largura e permitir uma altura máxima ilimitada ou definir uma largura exata, mas fornecer uma altura limitada.
A próxima seção descreve como essas restrições são transmitidas de um pai para um filho.
Como as restrições são transmitidas do pai para o filho
Durante a primeira etapa do algoritmo descrito em Restrições na fase de layout, as restrições são transmitidas do pai para o filho na árvore da interface.
Quando um nó pai mede os filhos, ele fornece essas restrições a cada filho para que eles saibam o tamanho que podem ter. Em seguida, ao decidir o próprio tamanho, ele também segue as restrições transmitidas pelos pais.
De modo geral, o algoritmo funciona da seguinte maneira:
- Para decidir o tamanho que realmente quer ocupar, o nó raiz na árvore de IU mede os filhos e encaminha as mesmas restrições para o primeiro filho.
- Se o filho for um modificador que não afeta a medição, ele encaminhará as restrições para o próximo modificador. As restrições são transmitidas pela cadeia de modificadores como estão, a menos que um modificador que afete a medição seja alcançado. As restrições são redimensionadas de acordo.
- Quando um nó que não tem filhos (chamado de "nó folha") é alcançado, ele decide o tamanho com base nas restrições transmitidas e retorna esse tamanho resolvido para o pai.
- O pai adapta as restrições com base nas medições desse filho e chama o próximo filho com essas restrições ajustadas.
- Depois que todos os filhos de um pai são medidos, o nó pai decide o próprio tamanho e comunica isso ao pai dele.
- Dessa forma, toda a árvore é percorrida em profundidade. Por fim, todos os nós decidem os tamanhos, e a etapa de medição é concluída.
Para ver um exemplo detalhado, assista ao vídeo Restrições e ordem de modificadores (link em inglês).
Modificadores que afetam as restrições
Na seção anterior, você aprendeu que alguns modificadores podem afetar o tamanho da restrição. As seções a seguir descrevem modificadores específicos que afetam as restrições.
O modificador size
O modificador size declara o tamanho preferencial do conteúdo.
Por exemplo, a árvore de interface abaixo precisa ser renderizada em um contêiner de 300dp
por 200dp. As restrições são limitadas, permitindo larguras entre 100dp e
300dp e alturas entre 100dp e 200dp:
O modificador size adapta as restrições recebidas para corresponder ao valor transmitido a ele.
Neste exemplo, o valor é 150dp:
size ajusta as restrições para 150dp.Se a largura e a altura forem menores que o menor limite de restrição ou maiores que o maior limite de restrição, o modificador vai corresponder às restrições transmitidas o mais próximo possível, ainda aderindo às restrições transmitidas:
size que segue a restrição transmitida o mais próximo
possível.Não é possível encadear vários modificadores size. O primeiro modificador size
define as restrições mínima e máxima como um valor fixo. Mesmo que
o segundo modificador de tamanho solicite um tamanho menor ou maior, ele ainda precisa
aderir aos limites exatos transmitidos, para que não substitua esses valores:
size, em que o segundo valor transmitido (50dp) não substitui o primeiro (100dp).O modificador requiredSize
Use o modificador requiredSize em vez de size se você precisar que o
nó substitua as restrições de entrada. O modificador requiredSize substitui
as restrições recebidas e transmite o tamanho especificado como limites exatos.
Quando o tamanho é transmitido de volta para a árvore, o nó filho é centralizado no espaço disponível:
requiredSize substituindo as restrições de entrada do
modificador size.Os modificadores width e height
O modificador size adapta a largura e a altura das restrições. Com
o modificador width, é possível definir uma largura fixa, mas deixar a altura indefinida.
Da mesma forma, com o modificador height, é possível definir uma altura fixa, mas deixar a
largura indefinida:
width e o modificador height definem uma largura
e uma altura fixas, respectivamente.O modificador sizeIn
O modificador sizeIn permite definir restrições exatas de mínimo e máximo
para largura e altura. Use o modificador sizeIn se precisar de um controle detalhado
sobre as restrições.
sizeIn com minWidth, maxWidth, minHeight e
maxHeight definidos.Exemplos
Nesta seção, mostramos e explicamos a saída de vários snippets de código com modificadores encadeados.
Image( painterResource(R.drawable.hero), contentDescription = null, Modifier .fillMaxSize() .size(50.dp) )
Esse snippet produz a seguinte saída:
Image preenche o tamanho máximo como
resultado da cadeia de modificadores.- O modificador
fillMaxSizemuda as restrições para definir a largura e a altura mínimas como o valor máximo:300dpde largura e200dpde altura. - Mesmo que o modificador
sizequeira usar um tamanho de50dp, ele ainda precisa aderir às restrições mínimas de entrada. Portanto, o modificadorsizetambém vai gerar os limites exatos de restrição de300por200, ignorando o valor fornecido no modificadorsize. - O
Imagesegue esses limites e informa um tamanho de300por200, que é transmitido por toda a árvore.
Image( painterResource(R.drawable.hero), contentDescription = null, Modifier .fillMaxSize() .wrapContentSize() .size(50.dp) )
Esse snippet produz a seguinte saída:
Image é centralizado e dimensionado para
50dp.- O modificador
fillMaxSizeadapta as restrições para definir a largura e a altura mínimas como o valor máximo:300dpna largura e200dpna altura. - O modificador
wrapContentSizeredefine as restrições mínimas. Portanto, enquantofillMaxSizeresultou em restrições fixas,wrapContentSizeas redefine para restrições limitadas. O nó seguinte pode ocupar todo o espaço novamente ou ser menor que o espaço inteiro. - O modificador
sizedefine as restrições para os limites mínimo e máximo de50. - O
Imageé resolvido para um tamanho de50por50, e o modificadorsizeencaminha isso. - O modificador
wrapContentSizetem uma propriedade especial. Ele usa o filho e o coloca no centro dos limites mínimos disponíveis que foram transmitidos a ele. O tamanho que ele comunica aos pais é igual aos limites mínimos que foram transmitidos a ele.
Ao combinar apenas três modificadores, é possível definir um tamanho para o elemento combinável e centralizá-lo no pai.
Image( painterResource(R.drawable.hero), contentDescription = null, Modifier .clip(CircleShape) .padding(10.dp) .size(100.dp) )
Esse snippet produz a seguinte saída:
- O modificador
clipnão muda as restrições. - O modificador
paddingreduz as restrições máximas. - O modificador
sizedefine todas as restrições como100dp. - O
Imagesegue essas restrições e informa um tamanho de100dppor100dp. - O modificador
paddingadiciona10dpem todos os lados ao tamanho informado peloImage. Assim, o layout com padding informa uma largura e altura de120dp. - Agora, na fase de desenho, o modificador
clipatua em uma tela de120dppor120dp. Ele cria uma máscara circular desse tamanho. - O modificador
paddinginsere o conteúdo por10dpem todos os lados, o que reduz o tamanho da tela para oImagepara100dppor100dp. - O
Imageé desenhado nessa tela menor. A imagem é cortada com base no círculo original de120dp, então a saída é um resultado não redondo.