Skip to content
CrossFly is 100% open sourceFollow us on GitHub
CrossFlyCrossFly
Get started

This page was machine-translated from Portuguese and may contain errors. The Portuguese version is canonical.

How to place a badge on the corner of an avatar

Purpose. Overlay a small “badge” (notification counter, status dot) anchored to a corner of another component (avatar, icon). It uses RelativeLayout, which positions children by anchors relative to another child.

APIs used

  • new RelativeLayout() — layout that positions by RelPos anchors and sizes by RelSize.
  • layout.add(Component target, RelPos x, RelPos y, RelSize w, RelSize h, Component relative) — adds target positioned relative to relative.
  • RelPos.END_OF — aligns the badge’s end (right) edge with the avatar’s end edge.
  • RelPos.START — aligns the badge’s top with the avatar’s top (vertical START anchor).
  • RelSize.AUTOSIZE — the badge uses its own preferred size (width and height).
  • container.setLayout(layout) — installs the RelativeLayout on the container.

Important verification: in source, the enum values are RelSize.AUTOSIZE (not AUTO), RelSize.FILL, RelSize.FIT, RelSize.SAMESIZE, RelSize.KEEPSIZE; and RelPos.END_OF, RelPos.START, RelPos.AFTER, RelPos.CENTER_OF etc.

Complete example (copy, paste and run)

package com.exemplo;

import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;

/** Runnable main screen. Point the launcher (classname) and run: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      // Example components: an "avatar" and a counter "badge"
      Component avatar = new Component().style(Styles.component().backColor(0xFFCCCCCC));
      Component badge  = new Label("3").style(Styles.component().backColor(0xFFFF3B30).textColor(0xFFFFFFFF));

      // Container holding avatar + badge
      Component container = new Component().style(Styles.transparent());
      RelativeLayout rl = new RelativeLayout();

      // 1) The avatar: anchored to the top-left corner, automatic size
      rl.add(avatar, RelPos.START, RelPos.START, RelSize.AUTOSIZE, RelSize.AUTOSIZE);

      // 2) The badge: top-right corner OF THE AVATAR (END_OF on x, START on y),
      //    with its own size. The last argument (avatar) is the reference.
      rl.add(badge, RelPos.END_OF, RelPos.START, RelSize.AUTOSIZE, RelSize.AUTOSIZE, avatar);

      container.setLayout(rl);
      add(container);
   }
}

The snippet below shows just the core. To run it, place it in the MainWindow skeleton above.

Minimal snippet

// Container holding avatar + badge
Component container = new Component().style(Styles.transparent());
RelativeLayout rl = new RelativeLayout();

// 1) The avatar: anchored to the top-left corner, automatic size
rl.add(avatar, RelPos.START, RelPos.START, RelSize.AUTOSIZE, RelSize.AUTOSIZE);

// 2) The badge: top-right corner OF THE AVATAR (END_OF on x, START on y),
//    with its own size. The last argument (avatar) is the reference.
rl.add(badge, RelPos.END_OF, RelPos.START, RelSize.AUTOSIZE, RelSize.AUTOSIZE, avatar);

container.setLayout(rl);
add(container);

Verification note (2026 code). Confirmed in RelativeLayout: the signature with an explicit reference is add(Component, RelPos, RelPos, RelSize, RelSize, Component). END_OF resolves x as “reference’s end edge minus the badge’s width” (the badge touches the avatar’s right side); START on y aligns to the top. To offset the badge “outward” from the corner (the classic overlap effect), adjust the badge’s outgap — there is an add(..., Component relative, Gap outgap) overload. If you omit the reference, the layout uses the previously added component as the reference.

Dig deeper

Was this page helpful?