style(ui): 播放页间距等宽 + 控制行上移 25 + 进度条重写

- 标题/歌手/专辑的间距统一为 10,视感更整齐
- 底部留白 70 -> 45(控制行上移 25)
- 进度条改用 LayoutBuilder + Positioned 绝对宽度,
  背景/缓冲/已播三层顺序明确,不再出现两端亮块
This commit is contained in:
2026-10-31 23:31:54 +08:00
parent 1c57d59d73
commit e3f72a69a9
+82 -65
View File
@@ -308,7 +308,7 @@ class _PlayerPageState extends BaseState<PlayerPage> {
Widget _buildMainPage(AudioService service, Song song, bool isPlaying) {
return Padding(
// 顶部留 16:与 AppBar/指示器拉开距离,避免封面贴着顶部
padding: const EdgeInsets.fromLTRB(24, 16, 24, 0),
padding: const EdgeInsets.fromLTRB(24, 24, 24, 0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@@ -366,17 +366,17 @@ class _PlayerPageState extends BaseState<PlayerPage> {
),
],
),
const SizedBox(height: 2),
const SizedBox(height: 10),
Text(
song.artist,
style: TextStyle(fontSize: 14, color: Colors.grey[400]),
style: TextStyle(fontSize: 16, color: Colors.grey[300]),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
// ---- 信息区(专辑 / 目录)----
if (_album.isNotEmpty || _folder.isNotEmpty) ...[
const SizedBox(height: 14),
const SizedBox(height: 10),
if (_album.isNotEmpty)
Text(
_album,
@@ -409,7 +409,8 @@ class _PlayerPageState extends BaseState<PlayerPage> {
// ---- 控制 ----
_buildControlButtons(service, song, isPlaying),
const SizedBox(height: 20),
// 底部多留 50px:控制行整体上移
const SizedBox(height: 45),
],
),
);
@@ -548,70 +549,86 @@ class _PlayerPageState extends BaseState<PlayerPage> {
Expanded(
child: SizedBox(
height: 24,
child: Stack(
alignment: Alignment.centerLeft,
children: [
Container(
height: 3,
decoration: BoxDecoration(
color: Colors.grey[800],
borderRadius: BorderRadius.circular(2),
),
),
FractionallySizedBox(
child: LayoutBuilder(
builder: (context, constraints) {
final width = constraints.maxWidth;
return Stack(
alignment: Alignment.centerLeft,
widthFactor: bufferProgress.clamp(0.0, 1.0),
child: Container(
height: 3,
decoration: BoxDecoration(
color: const Color(0xFF4A7A7A),
borderRadius: BorderRadius.circular(2),
),
),
),
FractionallySizedBox(
alignment: Alignment.centerLeft,
widthFactor: displayProgress.clamp(0.0, 1.0),
child: Container(
height: 3,
decoration: BoxDecoration(
color: const Color(0xFFB8D4D0),
borderRadius: BorderRadius.circular(2),
),
),
),
Positioned.fill(
child: SliderTheme(
data: SliderTheme.of(context).copyWith(
trackHeight: 0,
activeTrackColor: Colors.transparent,
inactiveTrackColor: Colors.transparent,
thumbColor: Colors.transparent,
overlayColor: Colors.transparent,
thumbShape: const RoundSliderThumbShape(
enabledThumbRadius: 0,
children: [
// 背景轨道
Positioned(
left: 0,
right: 0,
top: 10.5,
child: Container(
height: 3,
decoration: BoxDecoration(
color: Colors.grey[800],
borderRadius: BorderRadius.circular(2),
),
),
),
child: Slider(
value: displayProgress.clamp(0.0, 1.0),
min: 0.0,
max: 1.0,
onChanged: (value) {
setState(() => _dragProgress = value);
},
onChangeEnd: (value) {
final newPosition = Duration(
milliseconds:
(value * duration.inMilliseconds)
.round(),
);
service.seekTo(newPosition);
setState(() => _dragProgress = null);
},
// 已缓冲
Positioned(
left: 0,
top: 10.5,
child: Container(
width: width * bufferProgress.clamp(0.0, 1.0),
height: 3,
decoration: BoxDecoration(
color: const Color(0xFF4A7A7A),
borderRadius: BorderRadius.circular(2),
),
),
),
),
),
],
// 已播放
Positioned(
left: 0,
top: 10.5,
child: Container(
width:
width * displayProgress.clamp(0.0, 1.0),
height: 3,
decoration: BoxDecoration(
color: const Color(0xFFB8D4D0),
borderRadius: BorderRadius.circular(2),
),
),
),
Positioned.fill(
child: SliderTheme(
data: SliderTheme.of(context).copyWith(
trackHeight: 0,
activeTrackColor: Colors.transparent,
inactiveTrackColor: Colors.transparent,
thumbColor: Colors.transparent,
overlayColor: Colors.transparent,
thumbShape: const RoundSliderThumbShape(
enabledThumbRadius: 0,
),
),
child: Slider(
value: displayProgress.clamp(0.0, 1.0),
min: 0.0,
max: 1.0,
onChanged: (value) {
setState(() => _dragProgress = value);
},
onChangeEnd: (value) {
final newPosition = Duration(
milliseconds:
(value * duration.inMilliseconds)
.round(),
);
service.seekTo(newPosition);
setState(() => _dragProgress = null);
},
),
),
),
],
);
},
),
),
),