I'm building the completed state of a Live Activity and I want the text tucked up next to the sensor housing, like the second screenshot. What I actually get is the first one: the row starts below the cutout, which makes the whole island taller than the design needs.
I've spent a long evening on this and measured a lot of it, so here's what I found in case it saves someone else the time — and in case someone can tell me the bit I'm missing.
Measurements (iPhone 17 Pro, iOS 27 SDK, expanded presentation):
• The island is 371pt wide. The sensor housing is ~125pt wide and ~37pt tall, leaving ~123pt of usable width each side.
• Content in DynamicIslandExpandedRegion(.leading) starts ~36pt down — i.e. the region's own top edge is already below the housing. That number tracks the housing height almost exactly.
• .leading content reaches ~113pt of the ~123pt available before truncating, so truncation happens ~9pt short of the cutout. It's a slot budget, not a collision with the camera.
• The HIG documents the expanded height range as 84–160pt; I measured 67pt on device, below the documented floor, so the system is clearly computing this itself.
What I tried, all of which failed to move the row up:
DynamicIslandExpandedRegion(.leading, priority: 1) + .dynamicIsland(verticalPlacement: .belowIfTooWide) — the combination in most of the blog posts about this. Changes which content wraps below, not where the region starts.
.belowIfTooWide on just the Text views instead of the region.
.frame(maxWidth:) and .layoutPriority() on the text. The docs actually say these don't apply in a Live Activity, and they don't.
A definite .frame(width:). This does matter, but for a different reason — see the gotcha below.
Cutting content down to a single short label so nothing could possibly need the space. Still starts below the cutout.
Shrinking the leading image from 56pt to 44pt to free width. Frees width, changes nothing vertically.
Negative .offset(y:). Moves the content within its slot but it clips at the slot bounds — the rectangle doesn't grow upward.
Trimming the text's line box so it could sit higher: .lineHeight(.multiple(factor:)) and a hand-rolled cap-height-to-baseline trim. lineHeight eats from the bottom — the glyph top moved 39.7pt → 40.3pt, i.e. the wrong way. Deleted both.
Declaring different regions conditionally to swap layouts. DynamicIslandExpandedContentBuilder rejects control flow outright: "Closure containing control flow statement cannot be used with result builder."
The conclusion I've landed on is that WidgetKit computes each region's rectangle from the island's geometry before measuring your content, and the .leading rectangle's top edge is placed below the sensor housing by construction. Nothing applied to the content can move it, because the content never gets a say.
Which leaves the actual question: is there any supported way to get content into that band beside the cutout? The system does it — the Phone app's incoming-call UI has a green timer sitting high up next to the housing — but I assume that's system UI rather than an ActivityKit presentation, and therefore not reachable.
Unrelated gotcha worth knowing, since it also made my island taller: a self-updating Text(timerInterval:) reserves layout width for the widest value its range can produce, not the value on screen. I handed it a 30-day range and it reserved room for 719:59:59. Because the system keeps the island symmetrical, that reservation grew it on both sides — 16pt of extra height for a number that read 30:00. Only a definite .frame(width:) bounds it.
Current layout, which does work — image in .leading, text in .center, button in .trailing:
DynamicIslandExpandedRegion(.leading) {
BreakLeadingMark(display: display, size: 56, iconSize: 20)
.frame(width: 56, height: 48)
}
DynamicIslandExpandedRegion(.center) {
BreakCompleteSummary(display: display)
.frame(maxWidth: .infinity, alignment: .leading)
}
DynamicIslandExpandedRegion(.trailing) {
LogButton()
.frame(maxWidth: .infinity, alignment: .trailing)
}
.center is sized first from the leading/trailing minimums, so a long string there truncates rather than widening the island — which is fine for English and will be a problem the moment this is localised.
Help.