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 para elementos combináveis, que definem os limites de largura e altura.
Esta página descreve como os modificadores encadeados afetam as restrições e, por sua vez, a medição e a colocação de elementos combináveis.
Modificadores na árvore da interface
Para entender como os modificadores se influenciam, é ú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 modificadores como nós de wrapper para os nós de layout:
Adicionar mais de um modificador a um elemento combinável cria uma cadeia de modificadores. Quando
você encadeia vários modificadores, cada nó de modificador encapsula o restante da cadeia
e o nó de layout dentro. Por exemplo, quando você encadeia um clip
e um
modificador size
, o nó de modificador clip
envolve o nó de modificador size
,
que envolve o nó de layout Image
.
Na fase de layout, o algoritmo que percorre a árvore permanece o mesmo, mas cada nó de modificador também é visitado. Dessa forma, um modificador pode mudar os requisitos de tamanho e a posição do modificador ou do nó de layout que ele envolve.
Conforme 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 simplesmente nós de layout que descrevem como
exibir os filhos.
Para resumir:
- Os modificadores agrupam 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 ele 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.
- Colocar filhos: cada nó filho é colocado em relação à posição do próprio nó.
O Constraints
ajuda 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 dessa faixa.
Tipos de restrições
Uma restrição pode ser uma das seguintes:
- Limitado: o nó tem largura e altura máximas e mínimas.
- Ilimitado: o nó não é restrito a nenhum tamanho. Os limites máximos de largura e altura são definidos como infinito.
- Exata: 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 acima. Por exemplo, uma restrição pode limitar a largura, permitindo 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 de pai para filho na árvore da interface.
Quando um nó pai mede os filhos, ele fornece essas restrições a cada um deles para que saibam o tamanho máximo ou mínimo permitido. Em seguida, quando ele decidir o próprio tamanho, ele também vai aderir às restrições transmitidas pelos próprios pais.
Em um nível alto, o algoritmo funciona da seguinte maneira:
- Para decidir o tamanho que ele realmente quer ocupar, o nó raiz na árvore da interface 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 vai encaminhar as restrições para o próximo modificador. As restrições são transmitidas para a cadeia de modificadores como estão, a menos que um modificador que afete a medição seja alcançado. O tamanho das restrições é alterado de acordo com isso.
- Quando um nó é alcançado que não tem filhos (chamado de "nó de folha"), 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 do filho e chama o próximo filho com essas restrições ajustadas.
- Depois que todas as crianças de um pai são medidas, o nó pai decide o próprio tamanho e comunica isso ao próprio pai.
- Dessa forma, toda a árvore é percorrida em profundidade. Eventualmente, todos os nós decidem os tamanhos, e a etapa de medição é concluída.
Para conferir um exemplo detalhado, assista ao vídeo Ordem de restrições e modificadores.
Modificadores que afetam restrições
Você aprendeu na seção anterior que alguns modificadores podem afetar o tamanho da restrição. As seções a seguir descrevem modificadores específicos que afetam as restrições.
Modificador size
O modificador size
declara o tamanho preferencial do conteúdo.
Por exemplo, a árvore de interface a seguir 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.
Neste exemplo, o valor é 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, mantendo as restrições transmitidas:
Encadear vários modificadores size
não funciona. O primeiro modificador size
define as restrições mínimas e máximas em um valor fixo. Mesmo que
o segundo modificador de tamanho solicite um tamanho menor ou maior, ele ainda precisa
seguir os limites exatos transmitidos para não substituir esses valores:
Modificador requiredSize
Use o modificador requiredSize
em vez de size
se precisar que o
nó substitua as restrições recebidas. 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:
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:
Modificador sizeIn
O modificador sizeIn
permite definir restrições mínimas e máximas exatas
para largura e altura. Use o modificador sizeIn
se precisar de um controle refinado
sobre as restrições.
Exemplos
Esta seção mostra e explica 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:
- O modificador
fillMaxSize
muda as restrições para definir a largura e a altura mínimas como o valor máximo:300dp
na largura e200dp
na altura. - Mesmo que o modificador
size
queira usar um tamanho de50dp
, ele ainda precisa seguir as restrições mínimas de entrada. Assim, o modificadorsize
também vai gerar os limites de restrição exatos de300
por200
, ignorando efetivamente o valor fornecido no modificadorsize
. - O
Image
segue esses limites e informa um tamanho de300
por200
, que é transmitido até a árvore.
Image( painterResource(R.drawable.hero), contentDescription = null, Modifier .fillMaxSize() .wrapContentSize() .size(50.dp) )
Esse snippet produz a seguinte saída:
- O modificador
fillMaxSize
adapta as restrições para definir a largura mínima e a altura para o valor máximo:300dp
na largura e200dp
na altura. - O modificador
wrapContentSize
redefine as restrições mínimas. Assim, enquantofillMaxSize
resultou em restrições fixas,wrapContentSize
redefiniu-o para restrições limitadas. O nó a seguir agora pode ocupar todo o espaço novamente ou ser menor que o espaço inteiro. - O modificador
size
define as restrições para os limites mínimo e máximo de50
. - O
Image
é resolvido para um tamanho de50
por50
, e o modificadorsize
encaminha isso. - O modificador
wrapContentSize
tem uma propriedade especial. Ele pega o elemento filho e o coloca no centro dos limites mínimos disponíveis que foram transmitidos a ele. O tamanho comunicado aos pais é igual aos limites mínimos transmitidos.
Combinando apenas três modificadores, é possível definir um tamanho para o elemento combinável e centralizá-lo no elemento 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
clip
não muda as restrições.- O modificador
padding
reduz as restrições máximas. - O modificador
size
define todas as restrições como100dp
. - O
Image
obedece a essas restrições e informa um tamanho de100
por100dp
. - O modificador
padding
adiciona10dp
em todos os tamanhos, aumentando a largura e a altura informadas em20dp
. - Agora, na fase de desenho, o modificador
clip
atua em uma tela de120
por120dp
. Assim, cria uma máscara de círculo desse tamanho. - O modificador
padding
insere o conteúdo por10dp
em todos os tamanhos, reduzindo o tamanho da tela para100
por100dp
. - O
Image
é desenhado nessa tela. A imagem é cortada com base no círculo original de120dp
. Portanto, a saída é um resultado não arredondado.
- O modificador