feat(ui): shared-element hero covers from search and recents to detail screens

Tab navigators get a HeroController (nested navigators have none, so
Heroes never flew inside tabs). Search result rows, recent-access items,
and artist discography cards tag their covers; Album/Artist/Downloaded
screens accept a heroTag and mount the matching Hero on the header
cover. Tags are scoped per list section to stay unique per page.
This commit is contained in:
zarzet
2026-07-14 09:09:49 +07:00
parent 702fc9825e
commit c580280890
7 changed files with 180 additions and 93 deletions
+9 -1
View File
@@ -23,6 +23,7 @@ class AlbumDetailHeader extends StatelessWidget {
this.appBarTitle,
this.leading,
this.backgroundColor,
this.heroTag,
});
final String title;
@@ -61,6 +62,10 @@ class AlbumDetailHeader extends StatelessWidget {
final Color? backgroundColor;
/// Shared-element tag: when set, the cover flies from the list item that
/// pushed this screen (which wraps its thumbnail in a matching [Hero]).
final Object? heroTag;
/// Shrinks long titles so up to three lines fit the header.
double _titleFontSize() {
final length = title.trim().length;
@@ -149,7 +154,7 @@ class AlbumDetailHeader extends StatelessWidget {
final coverSize = (constraints.maxWidth * 0.5)
.clamp(150.0, 210.0)
.toDouble();
return Container(
final cover = Container(
width: coverSize,
height: coverSize,
decoration: BoxDecoration(
@@ -169,6 +174,9 @@ class AlbumDetailHeader extends StatelessWidget {
child: coverBuilder!(context, coverSize),
),
);
return heroTag != null
? Hero(tag: heroTag!, child: cover)
: cover;
},
),
const SizedBox(height: 20),