RelativeLayout
Posiciona cada filho por âncoras — relativas ao contêiner ou a outro componente. Sua força única é ancorar A a B (um badge no canto de um avatar, um rótulo à direita de um ícone).
🔴 · Pacote:
dev.crossfly.ui.layout· Estende:Layout
Quando usar
- Ancorar um componente a outro (
AFTER,BEFORE,END_OF,CENTER_OF). - Sobreposições e composições finas (badge, selo, rótulo posicionado).
Quando NÃO usar
- Esqueleto “topo/conteúdo/base preenchendo a sobra” → prefira VerticalLayout
com
LAY_FILL(mais simples; ver a nota sobreFILL/FITabaixo).
add(...) — assinatura e semântica
public RelativeLayout add(Component alvo, RelPos x, RelPos y, RelSize larg, RelSize alt);
// + sobrecargas: (..., Component ref) (..., Gap outgap) (..., Component ref, Gap outgap)
Sem ref, a âncora é relativa ao componente anterior adicionado.
RelPos (posição, em UIConstants): START, CENTER, END, AFTER, BEFORE, CENTER_OF,
END_OF, SAMEPOS, AUTOPOS, AUTOPOSCENTERED, KEEPPOS.
RelSize (tamanho): AUTOSIZE, FILL, FIT, SAMESIZE, KEEPSIZE.
Exemplo completo (copiar, colar e rodar)
package com.exemplo;
import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.graphics.*;
/** Tela principal executável. Aponte o launcher (classname) e rode: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
@Override
public void onShow() throws Exception
{
super.onShow();
// Avatar + badge no canto do avatar + nome ao lado
RelativeLayout rl = new RelativeLayout();
Label avatar = new Label("👤");
avatar.getStyle().autoWidth(Relative.ofFont(3f)).autoHeight(Relative.ofFont(3f));
Label badge = new Label("9");
Label nome = new Label("Ana Silva");
rl.add(avatar, RelPos.START, RelPos.START, RelSize.AUTOSIZE, RelSize.AUTOSIZE);
rl.add(badge, RelPos.END_OF, RelPos.START, RelSize.AUTOSIZE, RelSize.AUTOSIZE, avatar); // canto do avatar
rl.add(nome, RelPos.AFTER, RelPos.CENTER_OF, RelSize.AUTOSIZE, RelSize.AUTOSIZE, avatar); // após o avatar
Component cabecalho = new Component();
cabecalho.setLayout(rl);
setLayout(new VerticalLayout(Position.START, Position.START));
add(LAY_AUTO, cabecalho);
add(LAY_FILL, new Component());
}
}
Os trechos abaixo mostram só o miolo (o que vai dentro de
onShow()). Para rodar, coloque-os no esqueletoMainWindowacima.
Uso básico
// Avatar + badge no canto do avatar + nome ao lado
RelativeLayout rl = new RelativeLayout();
ImageView avatar = new ImageView(/* foto */);
avatar.getStyle().autoWidth(Relative.ofFont(3f)).autoHeight(Relative.ofFont(3f));
Label badge = new Label("9");
Label nome = new Label("Ana Silva");
rl.add(avatar, RelPos.START, RelPos.START, RelSize.AUTOSIZE, RelSize.AUTOSIZE);
rl.add(badge, RelPos.END_OF, RelPos.START, RelSize.AUTOSIZE, RelSize.AUTOSIZE, avatar); // canto do avatar
rl.add(nome, RelPos.AFTER, RelPos.CENTER_OF, RelSize.AUTOSIZE, RelSize.AUTOSIZE, avatar); // após o avatar
Component cabecalho = new Component();
cabecalho.setLayout(rl);
Padrões úteis de âncora
- B à direita de A, alinhado:
add(b, RelPos.AFTER, RelPos.CENTER_OF, RelSize.AUTOSIZE, RelSize.AUTOSIZE, a). - Mesmo tamanho de A:
RelSize.SAMESIZE. - Card centralizado:
add(card, RelPos.CENTER, RelPos.CENTER, RelSize.AUTOSIZE, RelSize.AUTOSIZE). - Margem por regra: passe um
Gap.ofFont(0.5f)como último argumento (vira ooutgapda regra).
⚠️ Semântica exata de RelSize (não confunda)
FILL= largura/altura total do pai menos a margem — ignora a referência (não é “o espaço restante ao lado de A”).FIT= do canto do pai até a borda da referência (ex.: preencher até a esquerda/topo de A).- Para “um filho absorve a sobra ao lado dos outros” → use
HorizontalLayout/VerticalLayoutcomLAY_FILL, não oRelativeLayout.
Erros comuns
- Esperar que
FILLseja “o que sobra ao lado de A” (é o pai inteiro). - Ciclos de referência (A depende de B que depende de A) — ancore sempre em componentes já adicionados antes.
Veja também
- VerticalLayout (para o esqueleto de tela) · Responsividade
Esta página foi útil?Obrigado pelo feedback!