Skip to content

Commit 372c4fa

Browse files
committed
Document safe area best practices
1 parent 183e059 commit 372c4fa

File tree

1 file changed

+68
-0
lines changed

1 file changed

+68
-0
lines changed

docs/developer-guide/The-Components-Of-Codename-One.asciidoc

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,74 @@ As you can see from <<form-layout-layers-graphic,the graphic>>, `Form` has two l
8383

8484
NOTE: You still need to place components using layout managers in order to get them to appear in the right place when using the layered pane.
8585

86+
[[safe-areas]]
87+
==== Safe Areas
88+
89+
Modern phones frequently include display cut-outs, rounded corners, or persistent gesture/navigation indicators that overlap the physical screen edges. These intrusions are no longer limited to iOS—many recent Android devices behave the same way—so Codename One provides a "safe area" API to ensure your UI remains visible regardless of the device. The safe area is the portion of the display that is guaranteed to be unobstructed.
90+
91+
.Tabs with safe-area padding enabled
92+
image::img/safe-area-good.png[Tabs with safe-area padding enabled,scaledwidth=40%]
93+
94+
.Tabs without safe-area padding
95+
image::img/safe-area-missing.png[Tabs without safe-area padding,scaledwidth=40%]
96+
97+
===== Automatic Safe-Area Handling
98+
99+
`Form` calculates the safe region automatically, and core UI components that anchor themselves to the screen edges apply that information without additional work:
100+
101+
* `Toolbar` and the status bar placeholder respect the top safe margins so that titles and action buttons remain legible around notches.
102+
* `Tabs`, `Sheet`, and `FloatingActionButton` instances mark their internal containers as safe areas so navigation controls are padded above gesture/navigation bars.
103+
* UI fragment templates can opt-in to safe areas declaratively using the `safeArea` flag, ensuring generated components stay within the padded region.
104+
105+
This means that many applications will "just work" on devices such as the iPhone X/14 family or Android devices with edge-to-edge displays. You only need to intervene when you use custom containers that you position flush against a screen edge or when you perform your own painting.
106+
107+
===== Marking Your Own Containers as Safe
108+
109+
If you create a container that should always stay clear of the unsafe portions of the screen (for example, a bottom navigation bar, an on-screen joystick, or a floating tool palette), enable safe-area padding explicitly:
110+
111+
[source,java]
112+
----
113+
Form form = new Form(new BorderLayout());
114+
115+
Container bottomBar = new Container(BoxLayout.x());
116+
bottomBar.setSafeArea(true);
117+
bottomBar.addAll(new Button("Home"), new Button("Search"), new Button("Profile"));
118+
119+
form.add(BorderLayout.SOUTH, bottomBar);
120+
form.show();
121+
----
122+
123+
Safe-area padding is only applied when the container does **not** have a scrollable parent. For scrollable content we assume the user can scroll the component into view instead.
124+
125+
Most layouts never need to know where the safe area begins, but if you draw manually (e.g., inside `paint()` or on the glass pane) you can query it directly:
126+
127+
[source,java]
128+
----
129+
Form form = Display.getInstance().getCurrent();
130+
Rectangle safe = form.getSafeArea();
131+
132+
Graphics g = ...; // e.g. inside paint()
133+
g.setClip(safe.getX(), safe.getY(), safe.getWidth(), safe.getHeight());
134+
// Custom drawing code that should avoid the notch/gesture areas
135+
----
136+
137+
The rectangle returned by `Form#getSafeArea()` is updated automatically whenever the OS reports a change (rotation, multitasking gestures, showing/hiding the system navigation area, and so on). In unusual situations where you adjust the safe-area root yourself (for example, when animating a container in from off-screen) you can force a recalculation by calling `Form#setSafeAreaChanged()`.
138+
139+
===== Safe-Area Roots and Advanced Layouts
140+
141+
Safe-area padding is calculated relative to a "safe-area root". Forms are roots by default, but you can mark any container as a root using `Container#setSafeAreaRoot(true)` when you need precise control—for example, when preparing a side menu that starts off-screen and slides in:
142+
143+
[source,java]
144+
----
145+
Container drawer = new Container(BoxLayout.y());
146+
drawer.setSafeAreaRoot(true); // Ensure safe margins apply before the drawer is visible
147+
drawer.setSafeArea(true);
148+
----
149+
150+
Marking the drawer as both a root and a safe area prevents a "jump" the moment it becomes visible, because the safe padding is already applied while it is off-screen.
151+
152+
Remember that safe areas apply across platforms. Always verify your screens on actual devices (or in the Codename One simulator with a device skin that exposes cut-outs) to make sure critical UI elements remain inside the padded region.
153+
86154
The second layer is the glass pane which allows you to draw arbitrary things on top of everything. The order in the image is indeed accurate:
87155

88156
1. `ContentPane` is lowest

0 commit comments

Comments
 (0)