live activity: fix vertical centering on lock screen
GeometryReader as the layout root pinned content top-left, and forcing maxHeight:.infinity over-claimed the whole proposed height, centring the content below true vertical centre (bigger gap above) on the Lock Screen. Demote GeometryReader to a background side-channel that only measures the slot width for the rich-vs-compact branch; the content stays intrinsic-sized so the system vertically centres it itself.
This commit is contained in:
@@ -67,32 +67,46 @@ private struct FuelBoardLiveActivityView: View {
|
||||
|
||||
/// Below this ACTUAL proposed width we show the compact strip (CarPlay
|
||||
/// small / Watch smart stack); at/above it we show the full card. The
|
||||
/// decision is made from the real space the system hands the body via
|
||||
/// GeometryReader, NOT from ViewThatFits ideal-width measurement — the
|
||||
/// latter is broken for truncating text (a long station name inflates the
|
||||
/// "ideal" width past the iPhone Lock Screen and collapses the full card).
|
||||
/// decision is made from the real width the system hands the body, read
|
||||
/// via a background GeometryReader — NOT ViewThatFits ideal-width
|
||||
/// measurement (that's broken for truncating text: a long station name
|
||||
/// inflated the "ideal" width past the iPhone Lock Screen and collapsed
|
||||
/// the full card).
|
||||
private let compactWidthThreshold: CGFloat = 280
|
||||
|
||||
/// Measured slot width (drives the rich-vs-compact branch). Measured in a
|
||||
/// background GeometryReader so it does NOT act as the layout container:
|
||||
/// a GeometryReader root pins content top-left, and forcing a
|
||||
/// maxHeight:.infinity frame on it over-claims the whole proposed height,
|
||||
/// centring the content below true vertical centre (bigger gap above) on
|
||||
/// the Lock Screen. Measuring behind the scenes keeps the content
|
||||
/// intrinsic-sized so the system vertically centres it itself.
|
||||
@State private var slotWidth: CGFloat = 400
|
||||
|
||||
var body: some View {
|
||||
Link(destination: context.state.mapsURL) {
|
||||
GeometryReader { geo in
|
||||
Group {
|
||||
// Branch on the ACTUAL proposed width. iPhone/iPad offer the
|
||||
// full Lock Screen width (>= threshold) → rich card, no matter
|
||||
// how long the station name is. Truly small slots (CarPlay /
|
||||
// Watch) offer much less → compact strip.
|
||||
Group {
|
||||
if geo.size.width >= compactWidthThreshold {
|
||||
richBody
|
||||
} else {
|
||||
compactBody
|
||||
}
|
||||
if slotWidth >= compactWidthThreshold {
|
||||
richBody
|
||||
} else {
|
||||
compactBody
|
||||
}
|
||||
// A GeometryReader hands its content the FULL proposed frame
|
||||
// (content is otherwise pinned top-left), so centre the card
|
||||
// within that space — keeps the Lock Screen content vertically
|
||||
// aligned instead of sitting high.
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
|
||||
}
|
||||
// Fill the card width so the background measure reads the real
|
||||
// slot, not the intrinsic content width.
|
||||
.frame(maxWidth: .infinity)
|
||||
// Side-channel width measurement — never the layout container.
|
||||
.background(
|
||||
GeometryReader { geo in
|
||||
Color.clear
|
||||
.onAppear { slotWidth = geo.size.width }
|
||||
.onChange(of: geo.size.width) { _, w in slotWidth = w }
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user