From 7bf8d18f1834adb409f0b6afe035c2153f9855bf Mon Sep 17 00:00:00 2001 From: lxh2875931338 Date: Sun, 1 Nov 2026 00:09:27 +0800 Subject: [PATCH] =?UTF-8?q?fix(ui):=20=E5=8A=A0=E5=85=A5=E6=AD=8C=E5=8D=95?= =?UTF-8?q?=E5=BC=B9=E5=B1=82=E4=B8=8D=E5=86=8D=E8=A2=AB=E8=BF=B7=E4=BD=A0?= =?UTF-8?q?=E6=92=AD=E6=94=BE=E5=99=A8=E9=81=AE=E6=8C=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 原因:迷你播放器挂在 Navigator overlay 上,层级高于底部弹层, 弹层里的歌单列表被它盖住,看起来像"没读到歌单"。 (日志确认查询正常:读到 1 个歌单) - RouteManager 抽到 services/route_manager.dart,新增临时隐藏开关 - 打开"加入歌单"弹层时隐藏迷你播放器,关闭后恢复 - main.dart 的 shouldShow 改用 showMiniPlayer(原来直接读路由,开关不生效) - 弹层底部加 SafeArea minimum + 16px 余量,不再贴着手势区 真机验证:弹层正常显示 "TL / 1 首",底部留出安全距离。 --- lib/main.dart | 28 +++------------------ lib/pages/home_page.dart | 34 +++++++++++++++++++++----- lib/services/route_manager.dart | 34 ++++++++++++++++++++++++++ lib/widgets/add_to_playlist_sheet.dart | 11 +++++++-- 4 files changed, 74 insertions(+), 33 deletions(-) create mode 100644 lib/services/route_manager.dart diff --git a/lib/main.dart b/lib/main.dart index 55e3880..9891502 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -7,6 +7,7 @@ import 'package:permission_handler/permission_handler.dart'; import 'package:flutter/services.dart'; import 'services/audio_service.dart'; +import 'services/route_manager.dart'; import 'services/playback_service.dart'; import 'services/app_lifecycle_service.dart'; import 'services/webdav_service.dart'; @@ -107,28 +108,6 @@ void main() async { }); } -// ════════════════════════════════════════════════════════════ -// 路由管理器(控制 MiniPlayer 显示/隐藏) -// ════════════════════════════════════════════════════════════ -class RouteManager extends ChangeNotifier { - static final RouteManager _instance = RouteManager._internal(); - factory RouteManager() => _instance; - RouteManager._internal(); - - String _currentRoute = '/'; - String get currentRoute => _currentRoute; - - bool get showMiniPlayer => - _currentRoute != '/player' && _currentRoute != '/playlist'; - - void updateRoute(String route) { - if (_currentRoute != route) { - _currentRoute = route; - debugPrint('📌 路由更新: $route'); - notifyListeners(); - } - } -} // ════════════════════════════════════════════════════════════ // 导航观察者(监听路由变化) @@ -399,8 +378,7 @@ class _QTPlayerAppState extends State { animation: RouteManager(), builder: (context, _) { final routeManager = RouteManager(); - final shouldShow = routeManager.currentRoute != '/player' && - routeManager.currentRoute != '/playlist'; + final shouldShow = routeManager.showMiniPlayer; return AnimatedSwitcher( duration: const Duration(milliseconds: 300), @@ -436,4 +414,4 @@ class _QTPlayerAppState extends State { ), ); } -} +} \ No newline at end of file diff --git a/lib/pages/home_page.dart b/lib/pages/home_page.dart index 386387b..c6a00c4 100644 --- a/lib/pages/home_page.dart +++ b/lib/pages/home_page.dart @@ -436,9 +436,18 @@ class _HomePageState extends BaseState { delegate: SliverChildBuilderDelegate( (context, index) { final song = _favorites[index]; - return AnimatedOpacity( - opacity: 1.0, - duration: const Duration(milliseconds: 150), + return TweenAnimationBuilder( + key: ValueKey('fav-$_homeTab-$index'), + tween: Tween(begin: 0.0, end: 1.0), + duration: const Duration(milliseconds: 240), + curve: Curves.easeOutCubic, + builder: (context, t, child) => Opacity( + opacity: t, + child: Transform.translate( + offset: Offset(0, (1 - t) * 10), + child: child, + ), + ), child: Padding( padding: const EdgeInsets.symmetric(vertical: 2), child: ListTile( @@ -515,8 +524,20 @@ class _HomePageState extends BaseState { delegate: SliverChildBuilderDelegate( (context, index) { final playlist = _playlistSummaries[index]; - return Padding( - padding: const EdgeInsets.symmetric(vertical: 2), + return TweenAnimationBuilder( + key: ValueKey('pl-$_homeTab-$index'), + tween: Tween(begin: 0.0, end: 1.0), + duration: const Duration(milliseconds: 240), + curve: Curves.easeOutCubic, + builder: (context, t, child) => Opacity( + opacity: t, + child: Transform.translate( + offset: Offset(0, (1 - t) * 10), + child: child, + ), + ), + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 2), child: ListTile( contentPadding: EdgeInsets.zero, visualDensity: VisualDensity.compact, @@ -561,7 +582,8 @@ class _HomePageState extends BaseState { if (mounted) safeSetState(() {}); }, ), - ); + ), + ); }, childCount: _playlistSummaries.length, ), diff --git a/lib/services/route_manager.dart b/lib/services/route_manager.dart new file mode 100644 index 0000000..9eba161 --- /dev/null +++ b/lib/services/route_manager.dart @@ -0,0 +1,34 @@ +// lib/services/route_manager.dart +import 'package:flutter/foundation.dart'; + +/// 路由管理器(控制 MiniPlayer 显示/隐藏) +class RouteManager extends ChangeNotifier { + static final RouteManager _instance = RouteManager._internal(); + factory RouteManager() => _instance; + RouteManager._internal(); + + String _currentRoute = '/'; + String get currentRoute => _currentRoute; + + /// 弹层/对话框打开时临时隐藏迷你播放器,避免盖住内容 + bool _temporarilyHidden = false; + + bool get showMiniPlayer => + !_temporarilyHidden && + _currentRoute != '/player' && + _currentRoute != '/playlist'; + + void setTemporarilyHidden(bool hidden) { + if (_temporarilyHidden == hidden) return; + _temporarilyHidden = hidden; + notifyListeners(); + } + + void updateRoute(String route) { + if (_currentRoute != route) { + _currentRoute = route; + debugPrint('📌 路由更新: $route'); + notifyListeners(); + } + } +} diff --git a/lib/widgets/add_to_playlist_sheet.dart b/lib/widgets/add_to_playlist_sheet.dart index 7df2fa0..6860fcd 100644 --- a/lib/widgets/add_to_playlist_sheet.dart +++ b/lib/widgets/add_to_playlist_sheet.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import '../models/playlist_summary.dart'; import '../repositories/playlist_repository.dart'; +import '../services/route_manager.dart'; /// 把一首歌加入歌单的底部弹层。 /// @@ -26,11 +27,14 @@ Future showAddToPlaylistSheet( } if (!context.mounted) return; + RouteManager().setTemporarilyHidden(true); + try { await showModalBottomSheet( context: context, backgroundColor: const Color(0xFF1A1F1E), builder: (sheetContext) { return SafeArea( + minimum: const EdgeInsets.only(bottom: 12), child: Column( mainAxisSize: MainAxisSize.min, children: [ @@ -109,12 +113,15 @@ Future showAddToPlaylistSheet( }, ), ), - const SizedBox(height: 8), + const SizedBox(height: 16), ], ), ); }, ); + } finally { + RouteManager().setTemporarilyHidden(false); + } } Future _createPlaylistAndAdd( @@ -163,4 +170,4 @@ Future _createPlaylistAndAdd( SnackBar(content: Text('新建歌单失败: $e')), ); } -} +} \ No newline at end of file