fix: size Today tiles to their content so no card can clip - #49
Open
foureight84 wants to merge 1 commit into
Open
fix: size Today tiles to their content so no card can clip#49foureight84 wants to merge 1 commit into
foureight84 wants to merge 1 commit into
Conversation
The Sleep tile clipped its score on a Pixel 10 Pro XL — reported right after the
Activity/calories fix shipped, and the same class of bug across the whole grid.
**The font-scale fix could not have covered this.** It grew the tile height by
the user's font scale, which works when the content fits at 1.0 and only
overflows once text grows. The Sleep tile never fit: its column needs ~135dp
(30sp duration + 10dp + a 28dp stage bar + 10dp + a 32sp score row) and a 168dp
tile leaves ~111dp after the 16dp padding, the eyebrow row and the 8dp spacer.
Reproduced on the emulator at Pixel 10 Pro XL geometry at **font scale 1.0** —
the reported clip, with no font scaling involved at all. Scaling a box that is
already too small just scales the overflow.
So height is now driven by content instead of approximated:
- `TodayTile` uses `heightIn(min = 168.dp)` — a floor, not a fixed height.
- Each grid row is measured with `IntrinsicSize.Min` and its tiles get
`fillMaxHeight()`, so a row is exactly as tall as its tallest tile needs and
both tiles in it still match. The grid stays uniform; nothing clips.
This subsumes the font-scale multiplier, which is deleted: sp content grows, the
intrinsic measurement sees it, the tile grows. No sampling, no 1.6 clamp, no
breaking point to move.
**The gauge rings are fixed by the sweep too**, which the previous change
explicitly could not do. `GaugeTile` and `BpRingColumn` pin `VitalRingGauge` to a
dp literal and size its centre text off that same value (`size.value * 0.30f`.sp)
inside a `Box(modifier.size(size))`, so the value overflowed its own ring as text
grew. The rings now scale with the font scale, keeping ring and text
proportional; the tile grows to fit the bigger ring on its own.
**Stage-bar labels are measured, not guessed.** The bar showed a label whenever a
segment was >=10% of the width, a proxy that broke as text grew relative to the
bar: REM rendered as "RE" at 1.3 (visible in the report) and DEEP as "DEE" at
2.0. A truncated stage name reads as a different stage, so the label is now
measured against its segment's real width and dropped when it doesn't fit — the
colored segment still carries the meaning. Measured via onSizeChanged rather
than BoxWithConstraints, because subcomposition cannot answer the
IntrinsicSize.Min query the grid row now makes.
Verified on emulator-5554 at Pixel 10 Pro XL geometry (1344x2992 @ 480dpi):
| font scale | before | after |
|------------|-----------------|----------------------------------------|
| 1.0 | score clipped | 82 SCORE + DEEP/LIGHT/REM all visible |
| 1.3 | - | no clip; REM dropped, not truncated |
| 2.0 | - | no clip; only LIGHT fits, none clipped |
Activity keeps all three values at every scale. 875 unit tests green.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #47. The Sleep tile clips its score on a Pixel 10 Pro XL — the same class of bug as the Activity/calories clip, swept across the whole Today grid.
The font-scale fix could not have covered this
#47 grew the tile height by the user's font scale. That works when content fits at 1.0 and only overflows once text grows — which is the Activity tile. The Sleep tile never fit at all: its column needs ~135dp (30sp duration + 10dp + a 28dp stage bar + 10dp + a 32sp score row) and a 168dp tile leaves ~111dp after the 16dp padding, the eyebrow row and the 8dp spacer.
I reproduced it on the emulator at Pixel 10 Pro XL geometry at font scale 1.0 — the reported clip, with no font scaling involved:
82sliced off at the tile's bottom edge82 SCORE+DEEP / LIGHT / REMall visibleScaling a box that is already too small just scales the overflow.
Content-driven height
TodayTileusesheightIn(min = 168.dp)— a floor, not a fixed height.IntrinsicSize.Minand its tiles getfillMaxHeight(), so a row is exactly as tall as its tallest tile needs and both tiles in it still match.The grid stays uniform and nothing can clip, at any font scale, for any value a tile shows. This subsumes the font-scale multiplier, which is deleted — sp content grows, the intrinsic measurement sees it, the tile grows. No sampling, no 1.6 clamp, no breaking point to move.
Gauge rings — the gap #47 flagged but couldn't close
GaugeTileandBpRingColumnpinnedVitalRingGaugeto a dp literal while sizing its centre text off that same value (size.value * 0.30f.sp) inside aBox(modifier.size(size)), so the value overflowed its own ring as text grew. The rings now scale with the font scale, keeping ring and text proportional; the tile grows to fit the bigger ring on its own.Stage-bar labels are measured, not guessed
The bar showed a label whenever its segment was ≥10% of the width — a proxy that breaks as text grows relative to the bar.
REMrendered as "RE" at 1.3 (visible in the original report) andDEEPas "DEE" at 2.0. A truncated stage name reads as a different stage, so the label is now measured against its segment's real width and dropped when it doesn't fit; the colored segment still carries the meaning.Measured via
onSizeChangedrather thanBoxWithConstraints— subcomposition cannot answer theIntrinsicSize.Minquery the grid row now makes.Verification
Runtime-verified on
emulator-5554at Pixel 10 Pro XL geometry (1344×2992 @ 480dpi), before/after on the same seeded data:82 SCORE,DEEP/LIGHT/REMall visibleREMdropped rather than truncated to "RE"LIGHTfits, nothing truncatedActivity keeps all three values at every scale. 875 unit tests green,
assembleDebuggreen.Note the tile fix has no automated coverage — the repo has no
androidTestsource set, so this rests on the emulator matrix above. Adding Compose UI tests would needui-test-junit4and a new source set; happy to do that separately if you want it locked down.