基本功能完善

This commit is contained in:
DelLevin-Home
2026-03-07 00:40:01 +08:00
parent f2ab6a17ba
commit 082145ff79
39 changed files with 5726 additions and 867 deletions

View File

@@ -1,11 +1,14 @@
import 'dart:io';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart' as path;
import 'package:provider/provider.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import '../providers/app_provider.dart';
import '../models/data_models.dart';
import '../utils/toast_util.dart';
/// 影视海报墙页面
class MoviePostersPage extends StatefulWidget {
@@ -93,64 +96,96 @@ class _MoviePostersPageState extends State<MoviePostersPage> {
}
Widget _buildPosterGrid() {
return GridView.builder(
return MasonryGridView.count(
padding: const EdgeInsets.all(16),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 0.7,
crossAxisSpacing: 12,
mainAxisSpacing: 12,
),
crossAxisCount: 2,
mainAxisSpacing: 12,
crossAxisSpacing: 12,
itemCount: _posters.length,
itemBuilder: (context, index) {
final poster = _posters[index];
return _buildPosterItem(poster);
return _buildPosterItem(poster, index);
},
);
}
Widget _buildPosterItem(MoviePoster poster) {
Widget _buildPosterItem(MoviePoster poster, int index) {
// 根据索引生成不同的高度,实现瀑布流效果
final heights = [180.0, 220.0, 160.0, 200.0, 240.0, 190.0];
final height = heights[index % heights.length];
return GestureDetector(
onTap: () => _showPosterDetail(poster),
child: Container(
height: height,
decoration: BoxDecoration(
border: Border.all(color: const Color(0xFFE5E5E5)),
),
child: Stack(
fit: StackFit.expand,
children: [
// 海报图片
Image.file(
File(poster.posterPath),
fit: BoxFit.cover,
errorBuilder: (_, __, ___) => const Center(
child: Icon(
Icons.broken_image,
color: Color(0xFFCCCCCC),
),
),
),
// 删除按钮
Positioned(
top: 8,
right: 8,
child: GestureDetector(
onTap: () => _showDeleteDialog(poster),
child: Container(
padding: const EdgeInsets.all(4),
decoration: const BoxDecoration(
color: Colors.white,
),
child: const Icon(
Icons.close,
size: 18,
color: Colors.red,
),
),
),
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.08),
blurRadius: 8,
offset: const Offset(0, 2),
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Stack(
fit: StackFit.expand,
children: [
// 海报图片
Image.file(
File(poster.posterPath),
fit: BoxFit.cover,
errorBuilder: (_, __, ___) => const Center(
child: Icon(
Icons.broken_image,
color: Color(0xFFCCCCCC),
),
),
),
// 渐变遮罩(底部)
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
height: 40,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Colors.transparent,
Colors.black.withOpacity(0.3),
],
),
),
),
),
// 删除按钮
Positioned(
top: 8,
right: 8,
child: GestureDetector(
onTap: () => _showDeleteDialog(poster),
child: Container(
padding: const EdgeInsets.all(6),
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.9),
borderRadius: BorderRadius.circular(4),
),
child: const Icon(
Icons.close,
size: 16,
color: Colors.red,
),
),
),
),
],
),
),
),
);
}
@@ -208,9 +243,7 @@ class _MoviePostersPageState extends State<MoviePostersPage> {
_loadPosters();
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('添加成功')),
);
ToastUtil.show(context, '添加成功');
}
}
} catch (e) {
@@ -241,9 +274,7 @@ class _MoviePostersPageState extends State<MoviePostersPage> {
await context.read<AppProvider>().removeMoviePoster(poster.id);
Navigator.pop(context);
_loadPosters();
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('已删除')),
);
ToastUtil.show(context, '已删除');
},
child: const Text('删除', style: TextStyle(color: Colors.red)),
),