Pular para o conteúdo
CrossFly é 100% open sourceSiga no GitHub
CrossFlyCrossFly
Começar

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 âncoras RelPos e dimensiona por RelSize.
  • layout.add(Component target, RelPos x, RelPos y, RelSize w, RelSize h, Component relative) — adiciona target posicionado relativo a relative.
  • 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 o RelativeLayout no container.

Verificação importante: na fonte, os valores do enum são RelSize.AUTOSIZE (não AUTO), RelSize.FILL, RelSize.FIT, RelSize.SAMESIZE, RelSize.KEEPSIZE; e RelPos.END_OF, RelPos.START, RelPos.AFTER, RelPos.CENTER_OF etc.

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 MainWindow acima.

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_OF resolve x como “borda final da referência menos a largura do badge” (o badge encosta no lado direito do avatar); START em y alinha ao topo. Para deslocar o badge para “fora” do canto (efeito clássico de sobreposição), ajuste o outgap do badge — há uma sobrecarga add(..., Component relative, Gap outgap). Se você omitir a referência, o layout usa o componente adicionado anteriormente como referência.

Aprofunde-se

Esta página foi útil?