fix(ui): resolve collapsed header title overlap

This commit is contained in:
zarzet
2026-09-04 23:58:14 +07:00
parent 958b79ebca
commit 2ef2beb621
2 changed files with 61 additions and 4 deletions
+15 -4
View File
@@ -44,7 +44,6 @@ class AppSliverHeader extends StatelessWidget {
final colorScheme = Theme.of(context).colorScheme;
final topPadding = normalizedHeaderTopPadding(context);
final maxHeight = tokens.headerExpandedHeight + topPadding;
final minHeight = kToolbarHeight + topPadding;
final edgeInset = detailHeaderEdgeInset(context);
return SliverAppBar(
@@ -74,9 +73,21 @@ class AppSliverHeader extends StatelessWidget {
actions: actions,
flexibleSpace: LayoutBuilder(
builder: (context, constraints) {
final expandRatio =
((constraints.maxHeight - minHeight) / (maxHeight - minHeight))
.clamp(0.0, 1.0);
// SliverAppBar adds the platform's actual top safe-area inset to its
// extents. Deriving the collapse ratio from our requested heights
// left notched iPhones looking almost fully expanded even after the
// toolbar had collapsed, so the large title occupied the back
// button's space. Read the resolved sliver geometry instead.
final settings = context
.dependOnInheritedWidgetOfExactType<FlexibleSpaceBarSettings>();
final minExtent = settings?.minExtent ?? kToolbarHeight;
final maxExtent = settings?.maxExtent ?? maxHeight;
final currentExtent =
settings?.currentExtent ?? constraints.maxHeight;
final extentDelta = maxExtent - minExtent;
final expandRatio = extentDelta > 0
? ((currentExtent - minExtent) / extentDelta).clamp(0.0, 1.0)
: 0.0;
final leftPadding = _showLeading
? (_leadingClearance + edgeInset) -
(((_leadingClearance + edgeInset) - _contentMargin) *
+46
View File
@@ -341,6 +341,52 @@ void main() {
expect(style.fontSize, AppTokens.standard.headerExpandedTitleSize);
});
for (final platform in [TargetPlatform.iOS, TargetPlatform.android]) {
testWidgets(
'collapsed page title clears leading control on ${platform.name}',
(tester) async {
final controller = ScrollController();
addTearDown(controller.dispose);
final topInset = platform == TargetPlatform.iOS ? 59.0 : 24.0;
await tester.pumpWidget(
MaterialApp(
theme: AppTheme.light().copyWith(platform: platform),
home: MediaQuery(
data: MediaQueryData(
size: const Size(430, 932),
padding: EdgeInsets.only(top: topInset),
),
child: Scaffold(
body: CustomScrollView(
controller: controller,
slivers: const [
AppSliverHeader.page(title: 'Metadata'),
SliverToBoxAdapter(child: SizedBox(height: 1200)),
],
),
),
),
),
);
controller.jumpTo(AppTokens.standard.headerExpandedHeight);
await tester.pump();
final title = find.text('Metadata');
final backIcon = find.byIcon(Icons.arrow_back);
expect(
tester.getRect(title).overlaps(tester.getRect(backIcon)),
isFalse,
);
expect(
tester.widget<Text>(title).style?.fontSize,
AppTokens.standard.headerCollapsedTitleSize,
);
},
);
}
test('is the only collapsing header implementation left', () {
final offenders = _libSources()
.where(