Como colocar um badge no canto de um avatar
Propósito. Sobrepor um pequeno “badge” (contador de notificações, ponto de status)
ancorado a um canto de outro componente (avatar, ícone). Usa o RelativeLayout, que
posiciona filhos por âncoras relativas a outro filho.
APIs usadas
new RelativeLayout()— layout que posiciona por âncorasRelPose dimensiona porRelSize.layout.add(Component target, RelPos x, RelPos y, RelSize w, RelSize h, Component relative)— adicionatargetposicionado relativo arelative.RelPos.END_OF— alinha a borda final (direita) do badge com a borda final do avatar.RelPos.START— alinha o topo do badge com o topo do avatar (âncora vertical START).RelSize.AUTOSIZE— o badge usa seu próprio tamanho preferido (largura e altura).container.setLayout(layout)— instala oRelativeLayoutno container.
Verificação importante: na fonte, os valores do enum são
RelSize.AUTOSIZE(nãoAUTO),RelSize.FILL,RelSize.FIT,RelSize.SAMESIZE,RelSize.KEEPSIZE; eRelPos.END_OF,RelPos.START,RelPos.AFTER,RelPos.CENTER_OFetc.
Exemplo completo (copiar, colar e rodar)
package com.exemplo;
import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
/** 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();
setLayout(new VerticalLayout());
// Componentes de exemplo: um "avatar" e um "badge" contador
Component avatar = new Component().style(Styles.component().backColor(0xFFCCCCCC));
Component badge = new Label("3").style(Styles.component().backColor(0xFFFF3B30).textColor(0xFFFFFFFF));
// Container que segura avatar + badge
Component container = new Component().style(Styles.transparent());
RelativeLayout rl = new RelativeLayout();
// 1) O avatar: ancorado no canto superior-esquerdo, tamanho automático
rl.add(avatar, RelPos.START, RelPos.START, RelSize.AUTOSIZE, RelSize.AUTOSIZE);
// 2) O badge: canto superior-direito DO AVATAR (END_OF em x, START em y),
// tamanho próprio. O último argumento (avatar) é a referência.
rl.add(badge, RelPos.END_OF, RelPos.START, RelSize.AUTOSIZE, RelSize.AUTOSIZE, avatar);
container.setLayout(rl);
add(container);
}
}
O trecho abaixo mostra só o miolo. Para rodar, coloque-o no esqueleto
MainWindowacima.
Trecho mínimo
// Container que segura avatar + badge
Component container = new Component().style(Styles.transparent());
RelativeLayout rl = new RelativeLayout();
// 1) O avatar: ancorado no canto superior-esquerdo, tamanho automático
rl.add(avatar, RelPos.START, RelPos.START, RelSize.AUTOSIZE, RelSize.AUTOSIZE);
// 2) O badge: canto superior-direito DO AVATAR (END_OF em x, START em y),
// tamanho próprio. O último argumento (avatar) é a referência.
rl.add(badge, RelPos.END_OF, RelPos.START, RelSize.AUTOSIZE, RelSize.AUTOSIZE, avatar);
container.setLayout(rl);
add(container);
Nota de verificação (código 2026). Confirmado em
RelativeLayout: a assinatura com referência explícita éadd(Component, RelPos, RelPos, RelSize, RelSize, Component).END_OFresolve x como “borda final da referência menos a largura do badge” (o badge encosta no lado direito do avatar);STARTem y alinha ao topo. Para deslocar o badge para “fora” do canto (efeito clássico de sobreposição), ajuste ooutgapdo badge — há uma sobrecargaadd(..., Component relative, Gap outgap). Se você omitir a referência, o layout usa o componente adicionado anteriormente como referência.
Aprofunde-se
- Card clicável (composição com GridLayout): card-clicavel.md