fixed timetable ruler and day header overflowing at large system text sizes
Both have fixed geometry, so their text scaling is capped at 1.3. Ruler times shrink instead of wrapping into the period number and are only shown when they fit at the current scale. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -13,17 +13,19 @@ class _DayHeaderStrip extends StatelessWidget {
|
|||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) => Row(
|
// Fixed-height strip with a 28px day circle: unclamped accessibility
|
||||||
children: [
|
// sizes overflow it.
|
||||||
SizedBox(width: rulerWidth),
|
Widget build(BuildContext context) => MediaQuery.withClampedTextScaling(
|
||||||
for (var d = 0; d < 5; d++)
|
maxScaleFactor: 1.3,
|
||||||
Expanded(
|
child: Row(
|
||||||
child: _DayHeaderCell(
|
children: [
|
||||||
date: weekStart.addDays(d),
|
SizedBox(width: rulerWidth),
|
||||||
today: today,
|
for (var d = 0; d < 5; d++)
|
||||||
|
Expanded(
|
||||||
|
child: _DayHeaderCell(date: weekStart.addDays(d), today: today),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -95,20 +95,24 @@ class _PeriodRuler extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
return SizedBox(
|
// Fixed ruler width and period heights: past this the labels overlap.
|
||||||
width: width,
|
return MediaQuery.withClampedTextScaling(
|
||||||
child: Stack(
|
maxScaleFactor: 1.3,
|
||||||
clipBehavior: Clip.none,
|
child: SizedBox(
|
||||||
children: [
|
width: width,
|
||||||
for (final period in schedule.periods)
|
child: Stack(
|
||||||
Positioned(
|
clipBehavior: Clip.none,
|
||||||
top: layout.topOf(period),
|
children: [
|
||||||
height: layout.heightOf(period),
|
for (final period in schedule.periods)
|
||||||
left: 0,
|
Positioned(
|
||||||
right: 0,
|
top: layout.topOf(period),
|
||||||
child: _PeriodLabel(period: period, theme: theme),
|
height: layout.heightOf(period),
|
||||||
),
|
left: 0,
|
||||||
],
|
right: 0,
|
||||||
|
child: _PeriodLabel(period: period, theme: theme),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -155,7 +159,11 @@ class _PeriodLabel extends StatelessWidget {
|
|||||||
|
|
||||||
return LayoutBuilder(
|
return LayoutBuilder(
|
||||||
builder: (context, constraints) {
|
builder: (context, constraints) {
|
||||||
final showTimes = constraints.maxHeight >= 38;
|
// Both times plus the number, at the current text scale (9 + 9 + 14
|
||||||
|
// plus the 3px insets and some air — 38px at scale 1).
|
||||||
|
final scaler = MediaQuery.textScalerOf(context);
|
||||||
|
final needed = 2 * scaler.scale(9) + scaler.scale(14) + 6;
|
||||||
|
final showTimes = constraints.maxHeight >= needed;
|
||||||
return DecoratedBox(
|
return DecoratedBox(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
border: Border(top: BorderSide(color: dividerColor, width: 0.5)),
|
border: Border(top: BorderSide(color: dividerColor, width: 0.5)),
|
||||||
@@ -169,11 +177,10 @@ class _PeriodLabel extends StatelessWidget {
|
|||||||
top: 3,
|
top: 3,
|
||||||
left: 0,
|
left: 0,
|
||||||
right: 0,
|
right: 0,
|
||||||
child: Text(
|
child: _timeText(
|
||||||
_format(period.start),
|
_format(period.start),
|
||||||
style: timeStyle,
|
timeStyle,
|
||||||
textAlign: TextAlign.center,
|
tightTextHeight,
|
||||||
textHeightBehavior: tightTextHeight,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
@@ -191,11 +198,10 @@ class _PeriodLabel extends StatelessWidget {
|
|||||||
bottom: 3,
|
bottom: 3,
|
||||||
left: 0,
|
left: 0,
|
||||||
right: 0,
|
right: 0,
|
||||||
child: Text(
|
child: _timeText(
|
||||||
_format(period.end),
|
_format(period.end),
|
||||||
style: timeStyle,
|
timeStyle,
|
||||||
textAlign: TextAlign.center,
|
tightTextHeight,
|
||||||
textHeightBehavior: tightTextHeight,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -205,6 +211,24 @@ class _PeriodLabel extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The ruler is narrow: a scaled-up time must shrink, never wrap into the
|
||||||
|
/// period number.
|
||||||
|
static Widget _timeText(
|
||||||
|
String text,
|
||||||
|
TextStyle? style,
|
||||||
|
TextHeightBehavior heightBehavior,
|
||||||
|
) => FittedBox(
|
||||||
|
fit: BoxFit.scaleDown,
|
||||||
|
child: Text(
|
||||||
|
text,
|
||||||
|
style: style,
|
||||||
|
maxLines: 1,
|
||||||
|
softWrap: false,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
textHeightBehavior: heightBehavior,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
static String _format(TimeOfDay t) =>
|
static String _format(TimeOfDay t) =>
|
||||||
'${t.hour.toString().padLeft(2, '0')}:${t.minute.toString().padLeft(2, '0')}';
|
'${t.hour.toString().padLeft(2, '0')}:${t.minute.toString().padLeft(2, '0')}';
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user