WanderndesCover ersetzt Hero-Übergang: Cover wandert live mit progress

This commit is contained in:
Hermes (Server)
2026-08-29 14:50:40 +02:00
parent 9d0cb90a51
commit a1eb5831e0
4 changed files with 161 additions and 12 deletions
+36 -5
View File
@@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:ui' show lerpDouble;
import 'package:audio_service/audio_service.dart';
import 'package:flutter/material.dart';
@@ -7,6 +8,7 @@ import 'package:provider/provider.dart';
import '../library/database.dart';
import '../services/navidrome_service.dart';
import '../shared/cover.dart';
import '../shared/favorite_button.dart';
import '../shared/server_favorite_button.dart';
import '../shared/theme.dart';
@@ -101,11 +103,6 @@ class NowPlayingScreen extends StatelessWidget {
}
}
/// Gemeinsamer Name des Coverbilds in Mini-Player und Vollbild — bis Task 6
/// (WanderndesCover) den bisherigen Hero-Übergang vollständig ersetzt hat,
/// nutzt `mini_player.dart` diesen Namen noch für sein eigenes Hero-Cover.
const coverHeldenName = 'melo-cover';
/// Schlüssel des Cover-Platzhalters — Task 6 misst darüber die tatsächliche
/// Vollbild-Position/-Größe des Covers (`RenderBox.localToGlobal`), statt
/// `NowPlayingScreen`s responsives Layout (Row/Column-Weiche, AspectRatio)
@@ -122,6 +119,40 @@ class _CoverPlatzhalter extends StatelessWidget {
AspectRatio(key: coverPlatzhalterKey, aspectRatio: 1, child: const SizedBox());
}
/// Cover-Bild, das zwischen Mini-Player- und Vollbild-Rechteck wandert.
///
/// Ersetzt die frühere `Hero`-Animation: die feuert nur bei echten
/// Navigator-Transitions, und `NowPlayingScreen` ist seit dem Overlay-Umbau
/// keine Route mehr. Positionierung/Größe kommen direkt aus [progress],
/// live an die Zugstrecke der Wischgeste gekoppelt.
class WanderndesCover extends StatelessWidget {
const WanderndesCover({
super.key,
required this.progress,
required this.artUri,
required this.miniRect,
required this.vollbildRect,
});
final double progress;
final Uri? artUri;
final Rect miniRect;
final Rect vollbildRect;
static const _miniRadius = 6.0;
static const _vollbildRadius = 16.0;
@override
Widget build(BuildContext context) {
final rect = Rect.lerp(miniRect, vollbildRect, progress)!;
final radius = lerpDouble(_miniRadius, _vollbildRadius, progress)!;
return Positioned.fromRect(
rect: rect,
child: CoverImage(artUri: artUri, radius: radius),
);
}
}
/// Die bisherigen AppBar-Actions (Songtext, Sleep-Timer, Warteschlange) als
/// eigene Kopfzeile statt echter AppBar — eine Route/Scaffold gibt es hier
/// nicht mehr.