fix(ui): 加入歌单弹层不再被迷你播放器遮挡
原因:迷你播放器挂在 Navigator overlay 上,层级高于底部弹层, 弹层里的歌单列表被它盖住,看起来像"没读到歌单"。 (日志确认查询正常:读到 1 个歌单) - RouteManager 抽到 services/route_manager.dart,新增临时隐藏开关 - 打开"加入歌单"弹层时隐藏迷你播放器,关闭后恢复 - main.dart 的 shouldShow 改用 showMiniPlayer(原来直接读路由,开关不生效) - 弹层底部加 SafeArea minimum + 16px 余量,不再贴着手势区 真机验证:弹层正常显示 "TL / 1 首",底部留出安全距离。
This commit is contained in:
+3
-25
@@ -7,6 +7,7 @@ import 'package:permission_handler/permission_handler.dart';
|
|||||||
|
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'services/audio_service.dart';
|
import 'services/audio_service.dart';
|
||||||
|
import 'services/route_manager.dart';
|
||||||
import 'services/playback_service.dart';
|
import 'services/playback_service.dart';
|
||||||
import 'services/app_lifecycle_service.dart';
|
import 'services/app_lifecycle_service.dart';
|
||||||
import 'services/webdav_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<QTPlayerApp> {
|
|||||||
animation: RouteManager(),
|
animation: RouteManager(),
|
||||||
builder: (context, _) {
|
builder: (context, _) {
|
||||||
final routeManager = RouteManager();
|
final routeManager = RouteManager();
|
||||||
final shouldShow = routeManager.currentRoute != '/player' &&
|
final shouldShow = routeManager.showMiniPlayer;
|
||||||
routeManager.currentRoute != '/playlist';
|
|
||||||
|
|
||||||
return AnimatedSwitcher(
|
return AnimatedSwitcher(
|
||||||
duration: const Duration(milliseconds: 300),
|
duration: const Duration(milliseconds: 300),
|
||||||
@@ -436,4 +414,4 @@ class _QTPlayerAppState extends State<QTPlayerApp> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -436,9 +436,18 @@ class _HomePageState extends BaseState<HomePage> {
|
|||||||
delegate: SliverChildBuilderDelegate(
|
delegate: SliverChildBuilderDelegate(
|
||||||
(context, index) {
|
(context, index) {
|
||||||
final song = _favorites[index];
|
final song = _favorites[index];
|
||||||
return AnimatedOpacity(
|
return TweenAnimationBuilder<double>(
|
||||||
opacity: 1.0,
|
key: ValueKey('fav-$_homeTab-$index'),
|
||||||
duration: const Duration(milliseconds: 150),
|
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(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 2),
|
padding: const EdgeInsets.symmetric(vertical: 2),
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
@@ -515,8 +524,20 @@ class _HomePageState extends BaseState<HomePage> {
|
|||||||
delegate: SliverChildBuilderDelegate(
|
delegate: SliverChildBuilderDelegate(
|
||||||
(context, index) {
|
(context, index) {
|
||||||
final playlist = _playlistSummaries[index];
|
final playlist = _playlistSummaries[index];
|
||||||
return Padding(
|
return TweenAnimationBuilder<double>(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 2),
|
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(
|
child: ListTile(
|
||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
visualDensity: VisualDensity.compact,
|
visualDensity: VisualDensity.compact,
|
||||||
@@ -561,7 +582,8 @@ class _HomePageState extends BaseState<HomePage> {
|
|||||||
if (mounted) safeSetState(() {});
|
if (mounted) safeSetState(() {});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
childCount: _playlistSummaries.length,
|
childCount: _playlistSummaries.length,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
|
|||||||
|
|
||||||
import '../models/playlist_summary.dart';
|
import '../models/playlist_summary.dart';
|
||||||
import '../repositories/playlist_repository.dart';
|
import '../repositories/playlist_repository.dart';
|
||||||
|
import '../services/route_manager.dart';
|
||||||
|
|
||||||
/// 把一首歌加入歌单的底部弹层。
|
/// 把一首歌加入歌单的底部弹层。
|
||||||
///
|
///
|
||||||
@@ -26,11 +27,14 @@ Future<void> showAddToPlaylistSheet(
|
|||||||
}
|
}
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
|
|
||||||
|
RouteManager().setTemporarilyHidden(true);
|
||||||
|
try {
|
||||||
await showModalBottomSheet<void>(
|
await showModalBottomSheet<void>(
|
||||||
context: context,
|
context: context,
|
||||||
backgroundColor: const Color(0xFF1A1F1E),
|
backgroundColor: const Color(0xFF1A1F1E),
|
||||||
builder: (sheetContext) {
|
builder: (sheetContext) {
|
||||||
return SafeArea(
|
return SafeArea(
|
||||||
|
minimum: const EdgeInsets.only(bottom: 12),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
@@ -109,12 +113,15 @@ Future<void> showAddToPlaylistSheet(
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 16),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
} finally {
|
||||||
|
RouteManager().setTemporarilyHidden(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _createPlaylistAndAdd(
|
Future<void> _createPlaylistAndAdd(
|
||||||
@@ -163,4 +170,4 @@ Future<void> _createPlaylistAndAdd(
|
|||||||
SnackBar(content: Text('新建歌单失败: $e')),
|
SnackBar(content: Text('新建歌单失败: $e')),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user