fix: center splash logo and wordmark (stack was sized to children)

Wrap AnimatedBuilder in SizedBox.expand so the Stack fills the full
Scaffold body; alignment: Alignment.center now centers within the whole
screen instead of within the wordmark-sized intrinsic box.

Adds a regression widget test (test/ui/splash_screen_test.dart) that
asserts the wordmark dx is within 1px of screen-center at 1500ms into
the animation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-12 07:37:54 +09:00
parent bf7720ebd3
commit c59454aa5f
2 changed files with 46 additions and 25 deletions
+27 -25
View File
@@ -57,34 +57,36 @@ class _SplashScreenState extends State<SplashScreen>
const gap = 3.0;
return Scaffold(
backgroundColor: const Color(0xFF0E1430),
body: AnimatedBuilder(
animation: _c,
builder: (context, _) {
final titleT = const Interval(0.60, 0.88, curve: Curves.easeOut)
.transform(_c.value);
return Stack(
alignment: Alignment.center,
children: [
for (var i = 0; i < _blocks.length; i++)
_block(i, blockSize, gap),
Transform.translate(
offset: Offset(0, 78 + 12 * (1 - titleT)),
child: Opacity(
opacity: titleT,
child: const Text(
'BLOCK SEASONS',
style: TextStyle(
fontSize: 26,
fontWeight: FontWeight.w900,
letterSpacing: 4,
color: Colors.white,
body: SizedBox.expand(
child: AnimatedBuilder(
animation: _c,
builder: (context, _) {
final titleT = const Interval(0.60, 0.88, curve: Curves.easeOut)
.transform(_c.value);
return Stack(
alignment: Alignment.center,
children: [
for (var i = 0; i < _blocks.length; i++)
_block(i, blockSize, gap),
Transform.translate(
offset: Offset(0, 78 + 12 * (1 - titleT)),
child: Opacity(
opacity: titleT,
child: const Text(
'BLOCK SEASONS',
style: TextStyle(
fontSize: 26,
fontWeight: FontWeight.w900,
letterSpacing: 4,
color: Colors.white,
),
),
),
),
),
],
);
},
],
);
},
),
),
);
}
+19
View File
@@ -0,0 +1,19 @@
import 'package:block_seasons/ui/screens/splash_screen.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('splash wordmark is horizontally centered', (tester) async {
await tester.pumpWidget(MaterialApp(
home: SplashScreen(nextScreen: () => const Scaffold(body: SizedBox())),
));
// Mid-animation: wordmark already laid out.
await tester.pump(const Duration(milliseconds: 1500));
final screenWidth = tester.getSize(find.byType(SplashScreen)).width;
final wordmark = tester.getCenter(find.text('BLOCK SEASONS'));
expect(wordmark.dx, closeTo(screenWidth / 2, 1.0));
// Drain the rest of the animation so no timers leak.
await tester.pump(const Duration(milliseconds: 600));
await tester.pumpAndSettle();
});
}