PrankSoundboard/lib/pages/category_detail_page.dart

171 lines
6.5 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import '../models/prank_category.dart';
import '../models/prank_sound.dart';
import '../managers/data_manager.dart';
import '../managers/sound_manager.dart';
import '../widgets/big_player_panel.dart';
class CategoryDetailPage extends StatefulWidget {
final PrankCategory category;
const CategoryDetailPage({super.key, required this.category});
@override
State<CategoryDetailPage> createState() => _CategoryDetailPageState();
}
class _CategoryDetailPageState extends State<CategoryDetailPage> {
@override
void dispose() {
SoundManager().stop();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
alignment: Alignment.bottomCenter,
children: [
CustomScrollView(
physics: const BouncingScrollPhysics(),
slivers: [
SliverAppBar(
expandedHeight: 200,
pinned: true,
backgroundColor: widget.category.themeColor,
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios_new, color: Colors.white),
onPressed: () => Navigator.pop(context),
),
flexibleSpace: FlexibleSpaceBar(
title: Text(widget.category.categoryName),
background: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
widget.category.themeColor,
widget.category.themeColor.withOpacity(0.7),
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
),
child: Stack(
children: [
Positioned(
right: -30,
bottom: -30,
child: Icon(Icons.music_note, size: 200, color: Colors.white.withOpacity(0.15)),
),
Center(
child: Icon(Icons.play_circle_fill, size: 60, color: Colors.white.withOpacity(0.3)),
)
],
),
),
),
),
SliverPadding(
padding: const EdgeInsets.fromLTRB(0, 20, 0, 250),
sliver: SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
final sound = widget.category.list[index];
return _buildSoundTile(context, sound);
},
childCount: widget.category.list.length,
),
),
),
],
),
// 详情页覆盖整个屏幕,不需要避让 BottomBar所以使用默认的 30 偏移
BigPlayerPanel(
themeColor: widget.category.themeColor,
bottomOffset: 30,
),
],
),
);
}
Widget _buildSoundTile(BuildContext context, PrankSound sound) {
final manager = SoundManager();
return ValueListenableBuilder<List<PrankSound>>(
valueListenable: DataManager().favoritesNotifier,
builder: (context, favorites, _) {
final isFav = sound.isFavorite;
return ValueListenableBuilder<PrankSound?>(
valueListenable: manager.currentSoundNotifier,
builder: (context, currentSound, _) {
final bool isActive = currentSound == sound;
return Container(
margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 8),
decoration: BoxDecoration(
color: isActive ? widget.category.themeColor.withOpacity(0.05) : Colors.white,
border: isActive ? Border.all(color: widget.category.themeColor, width: 2) : null,
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.02),
blurRadius: 10,
offset: const Offset(0, 4),
),
],
),
child: Material(
color: Colors.transparent,
child: InkWell(
borderRadius: BorderRadius.circular(20),
onTap: () => manager.play(sound),
child: Padding(
padding: const EdgeInsets.all(12),
child: Row(
children: [
Container(
width: 50,
height: 50,
decoration: BoxDecoration(
color: widget.category.themeColor.withOpacity(0.1),
borderRadius: BorderRadius.circular(15),
),
child: isActive
? Icon(Icons.equalizer, color: widget.category.themeColor)
: Icon(Icons.music_note, color: widget.category.themeColor),
),
const SizedBox(width: 16),
Expanded(
child: Text(
sound.title,
style: TextStyle(
fontWeight: isActive ? FontWeight.bold : FontWeight.normal,
fontSize: 16,
color: isActive ? widget.category.themeColor : const Color(0xFF1D1D35),
),
),
),
IconButton(
icon: Icon(
isFav ? Icons.favorite_rounded : Icons.favorite_border_rounded,
color: isFav ? const Color(0xFFFF6584) : Colors.grey[300],
),
onPressed: () {
DataManager().toggleFavorite(sound);
},
),
],
),
),
),
),
);
},
);
}
);
}
}