Switch display size to five symmetric levels

The discrete tick-slider UI lands Default at the slider's mid-point,
which matches how every other size control on a TV (volume, brightness,
font-size sliders) works. The previous four-level asymmetric layout
(two shrink steps, one growth step) was a discrete-picker decision
that didn't translate well once the UI became a slider: at four slots
Default sat at slot 2 of 4, off-centre.

DisplaySizeLevel proto enum gains EXTRA_LARGE = 4. The Kotlin enum
ordering already iterates UNRECOGNIZED last so existing UNRECOGNIZED
clamps still work. The string-array and individual level string
resources gain the Extra large entry.

Percentages are re-tuned to be symmetric around Default with growth
headroom slightly larger than shrink headroom (matches the demand
signal from the upstream discussion thread):

- Text:    XS 82  S 92  Default 100  L 110  XL 120
- Card:    XS 78  S 90  Default 100  L 115  XL 130
- Spacing: XS 75  S 88  Default 100  L 118  XL 135

The scaledSp lookup is regenerated for the new percentages and gains
an XL column. The formula fallback (rounded integer math) handles any
base sp not in the table.

Tests assert the new Card LARGE (115%) and Spacing LARGE (118%)
percentages against the dp math.
This commit is contained in:
Justin Visser 2026-05-28 14:23:20 +02:00
parent 8ff97daf44
commit 6cef3fbce7
4 changed files with 45 additions and 21 deletions

View file

@ -9,6 +9,7 @@ val displaySizeLevelDisplayOrder: List<DisplaySizeLevel> =
DisplaySizeLevel.SMALL,
DisplaySizeLevel.DEFAULT,
DisplaySizeLevel.LARGE,
DisplaySizeLevel.EXTRA_LARGE,
)
fun DisplaySizeLevel.scaledSp(baseSp: Int): TextUnit {
@ -22,14 +23,14 @@ fun DisplaySizeLevel.scaledSp(baseSp: Int): TextUnit {
10 -> 8
12 -> 10
13 -> 11
14 -> 12
14 -> 11
16 -> 13
18 -> 15
20 -> 17
20 -> 16
24 -> 20
28 -> 24
56 -> 47
64 -> 54
28 -> 23
56 -> 46
64 -> 52
else -> null
}
}
@ -52,18 +53,35 @@ fun DisplaySizeLevel.scaledSp(baseSp: Int): TextUnit {
}
DisplaySizeLevel.LARGE -> {
when (baseSp) {
10 -> 11
12 -> 13
13 -> 14
14 -> 15
16 -> 18
18 -> 20
20 -> 22
24 -> 26
28 -> 31
56 -> 62
64 -> 70
else -> null
}
}
DisplaySizeLevel.EXTRA_LARGE -> {
when (baseSp) {
10 -> 12
12 -> 14
13 -> 15
14 -> 16
13 -> 16
14 -> 17
16 -> 19
18 -> 21
20 -> 23
24 -> 28
28 -> 32
56 -> 65
64 -> 74
18 -> 22
20 -> 24
24 -> 29
28 -> 34
56 -> 67
64 -> 77
else -> null
}
}
@ -77,9 +95,10 @@ fun DisplaySizeLevel.scaledSp(baseSp: Int): TextUnit {
fun DisplaySizeLevel.textPercent(): Int =
when (this) {
DisplaySizeLevel.EXTRA_SMALL -> 84
DisplaySizeLevel.EXTRA_SMALL -> 82
DisplaySizeLevel.SMALL -> 92
DisplaySizeLevel.LARGE -> 116
DisplaySizeLevel.LARGE -> 110
DisplaySizeLevel.EXTRA_LARGE -> 120
DisplaySizeLevel.DEFAULT, DisplaySizeLevel.UNRECOGNIZED -> 100
}
@ -87,7 +106,8 @@ fun DisplaySizeLevel.cardPercent(): Int =
when (this) {
DisplaySizeLevel.EXTRA_SMALL -> 78
DisplaySizeLevel.SMALL -> 90
DisplaySizeLevel.LARGE -> 116
DisplaySizeLevel.LARGE -> 115
DisplaySizeLevel.EXTRA_LARGE -> 130
DisplaySizeLevel.DEFAULT, DisplaySizeLevel.UNRECOGNIZED -> 100
}
@ -95,6 +115,7 @@ fun DisplaySizeLevel.spacingPercent(): Int =
when (this) {
DisplaySizeLevel.EXTRA_SMALL -> 75
DisplaySizeLevel.SMALL -> 88
DisplaySizeLevel.LARGE -> 125
DisplaySizeLevel.LARGE -> 118
DisplaySizeLevel.EXTRA_LARGE -> 135
DisplaySizeLevel.DEFAULT, DisplaySizeLevel.UNRECOGNIZED -> 100
}

View file

@ -182,6 +182,7 @@ enum DisplaySizeLevel{
EXTRA_SMALL = 1;
SMALL = 2;
LARGE = 3;
EXTRA_LARGE = 4;
}
message InterfacePreferences {

View file

@ -405,6 +405,7 @@
<string name="display_size_level_small">Small</string>
<string name="display_size_level_default">Default</string>
<string name="display_size_level_large">Large</string>
<string name="display_size_level_extra_large">Extra large</string>
<string name="aspect_ratio">Aspect Ratio</string>
<string name="show_details">Show details</string>
<string name="image_type">Image type</string>
@ -606,6 +607,7 @@
<item>@string/display_size_level_small</item>
<item>@string/display_size_level_default</item>
<item>@string/display_size_level_large</item>
<item>@string/display_size_level_extra_large</item>
</string-array>
<string name="skip_ignore">Ignore</string>

View file

@ -118,8 +118,8 @@ class InterfaceHelpersTest {
),
cardSizeLevel = DisplaySizeLevel.LARGE,
)
// LARGE → cardPercent() = 116. 172 * 116 / 100 = 199 (integer truncation).
assertEquals(199, customization.cardHeightDp)
// LARGE → cardPercent() = 115. 172 * 115 / 100 = 197 (integer truncation).
assertEquals(197, customization.cardHeightDp)
}
@Test
@ -132,8 +132,8 @@ class InterfaceHelpersTest {
),
spacingLevel = DisplaySizeLevel.LARGE,
)
// LARGE → spacingPercent() = 125. BASE_SPACING_DP = 16. 16 * 125 / 100 = 20.
assertEquals(20, customization.spacingDp)
// LARGE → spacingPercent() = 118. BASE_SPACING_DP = 16. 16 * 118 / 100 = 18.
assertEquals(18, customization.spacingDp)
}
@Test