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 byRelPosanchors and sizes byRelSize.layout.add(Component target, RelPos x, RelPos y, RelSize w, RelSize h, Component relative)— addstargetpositioned relative torelative.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 theRelativeLayouton the container.
Important verification: in source, the enum values are
RelSize.AUTOSIZE(notAUTO),RelSize.FILL,RelSize.FIT,RelSize.SAMESIZE,RelSize.KEEPSIZE; andRelPos.END_OF,RelPos.START,RelPos.AFTER,RelPos.CENTER_OFetc.
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
MainWindowskeleton 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 isadd(Component, RelPos, RelPos, RelSize, RelSize, Component).END_OFresolves x as “reference’s end edge minus the badge’s width” (the badge touches the avatar’s right side);STARTon y aligns to the top. To offset the badge “outward” from the corner (the classic overlap effect), adjust the badge’soutgap— there is anadd(..., Component relative, Gap outgap)overload. If you omit the reference, the layout uses the previously added component as the reference.
Dig deeper
- Clickable card (composition with GridLayout): card-clicavel.md