Skip to content

Commit 5f37b32

Browse files
nattb8claude
andcommitted
feat(audience-sample): respect Android safe area in sample app UI (SDK-314)
Apply Screen.safeArea insets as root VisualElement padding so content is never obscured by the status bar, notch, or navigation bar on Android. Padding is updated every frame when the safe area rect changes (startup and orientation changes); a too-early call before layout is settled retries automatically the following frame. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent ee95a08 commit 5f37b32

1 file changed

Lines changed: 38 additions & 0 deletions

File tree

examples/audience/Assets/SampleApp/Scripts/AudienceSample.UI.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ private static readonly (string TabId, string PanelId)[] Tabs =
8484

8585
#pragma warning restore 8618
8686

87+
// Tracks the last applied safe area so Update only re-applies on change.
88+
private Rect _lastSafeArea;
89+
8790
// ---- UI lifecycle (single entry point called from main's Awake) ----
8891

8992
// Full UI lifecycle: thread capture, document load, binding, callbacks,
@@ -113,6 +116,15 @@ private void InitializeUi()
113116
_root.schedule.Execute(RefreshStatusBar).Every(StatusPollIntervalMs);
114117
}
115118

119+
// Re-apply safe-area padding whenever Screen.safeArea changes (startup,
120+
// orientation flip, multi-window resize). Runs every frame but exits
121+
// immediately when nothing has changed.
122+
private void Update()
123+
{
124+
if (Screen.safeArea != _lastSafeArea)
125+
ApplySafeArea();
126+
}
127+
116128
// ---- UI document load ----
117129

118130
// Loads the UXML/USS resources and clones the tree into the panel
@@ -444,6 +456,32 @@ void Update()
444456
_root.schedule.Execute(Update).StartingIn(0);
445457
}
446458

459+
// Converts Screen.safeArea insets (screen-space pixels) to root
460+
// VisualElement padding (panel layout units). Called by Update() on
461+
// every frame where the safe area rect changes — typically once on
462+
// startup and once per orientation change.
463+
//
464+
// _lastSafeArea is updated only on success so that a too-early call
465+
// (layout not yet settled) retries automatically next frame.
466+
private void ApplySafeArea()
467+
{
468+
if (_root == null) return;
469+
var w = _root.layout.width;
470+
var h = _root.layout.height;
471+
if (float.IsNaN(w) || w <= 0f || float.IsNaN(h) || h <= 0f) return;
472+
473+
var safe = Screen.safeArea;
474+
var scaleX = w / Screen.width;
475+
var scaleY = h / Screen.height;
476+
477+
_root.style.paddingTop = (Screen.height - safe.yMax) * scaleY;
478+
_root.style.paddingBottom = safe.y * scaleY;
479+
_root.style.paddingLeft = safe.x * scaleX;
480+
_root.style.paddingRight = (Screen.width - safe.xMax) * scaleX;
481+
482+
_lastSafeArea = safe;
483+
}
484+
447485
// ---- Typed-events accordion construction ----
448486

449487
// Each accordion's Send button captures its EventSpec + input dictionary

0 commit comments

Comments
 (0)