generated from dellevin/template
适配平板
This commit is contained in:
@@ -15,8 +15,9 @@ import 'movie_share_page.dart';
|
||||
/// 影视详情页 - 极简主义设计
|
||||
class MovieDetailPage extends StatefulWidget {
|
||||
final Movie movie;
|
||||
final bool embedded;
|
||||
|
||||
const MovieDetailPage({super.key, required this.movie});
|
||||
const MovieDetailPage({super.key, required this.movie, this.embedded = false});
|
||||
|
||||
@override
|
||||
State<MovieDetailPage> createState() => _MovieDetailPageState();
|
||||
@@ -119,8 +120,12 @@ class _MovieDetailPageState extends State<MovieDetailPage> {
|
||||
child: Row(children: [
|
||||
const SizedBox(width: 4),
|
||||
IconButton(
|
||||
icon: Icon(Icons.arrow_back_ios_new, color: colors.onSurface, size: 18),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
icon: widget.embedded
|
||||
? Icon(Icons.close, color: colors.onSurface, size: 18)
|
||||
: Icon(Icons.arrow_back_ios_new, color: colors.onSurface, size: 18),
|
||||
onPressed: widget.embedded
|
||||
? () => context.read<AppProvider>().selectMovie(null)
|
||||
: () => Navigator.pop(context),
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Expanded(
|
||||
@@ -186,8 +191,12 @@ class _MovieDetailPageState extends State<MovieDetailPage> {
|
||||
child: Row(children: [
|
||||
const SizedBox(width: 4),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.arrow_back_ios_new, color: Colors.white, size: 18),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
icon: widget.embedded
|
||||
? const Icon(Icons.close, color: Colors.white, size: 18)
|
||||
: const Icon(Icons.arrow_back_ios_new, color: Colors.white, size: 18),
|
||||
onPressed: widget.embedded
|
||||
? () => context.read<AppProvider>().selectMovie(null)
|
||||
: () => Navigator.pop(context),
|
||||
),
|
||||
ValueListenableBuilder<bool>(
|
||||
valueListenable: _showTitle,
|
||||
@@ -1180,9 +1189,14 @@ class _MovieDetailPageState extends State<MovieDetailPage> {
|
||||
final provider = context.read<AppProvider>();
|
||||
await provider.removeMovie(widget.movie.id);
|
||||
if (!mounted) return;
|
||||
final navigator = Navigator.of(context);
|
||||
navigator.pop();
|
||||
navigator.pop();
|
||||
if (widget.embedded) {
|
||||
Navigator.of(context).pop(); // close dialog
|
||||
provider.selectMovie(null);
|
||||
} else {
|
||||
final navigator = Navigator.of(context);
|
||||
navigator.pop();
|
||||
navigator.pop();
|
||||
}
|
||||
if (mounted) {
|
||||
ToastUtil.show(context, '已删除');
|
||||
}
|
||||
|
||||
@@ -8,6 +8,10 @@ import '../../widgets/movie_list_item.dart';
|
||||
import '../../widgets/animated_star_rating.dart';
|
||||
import '../../widgets/shimmer_skeleton.dart';
|
||||
import '../../widgets/fade_in_local_image.dart';
|
||||
import '../../utils/responsive.dart';
|
||||
import '../../widgets/master_detail_scaffold.dart';
|
||||
import '../../widgets/detail_placeholder.dart';
|
||||
import 'movie_detail_page.dart';
|
||||
|
||||
/// 观影标签页(分页 + 触底加载)
|
||||
class MovieTabPage extends StatefulWidget {
|
||||
@@ -119,16 +123,37 @@ class _MovieTabPageState extends State<MovieTabPage> {
|
||||
await _loadFirst();
|
||||
}
|
||||
|
||||
void _onMovieTap(Movie movie) {
|
||||
if (Breakpoint.isWideContent(context)) {
|
||||
context.read<AppProvider>().selectMovie(movie);
|
||||
} else {
|
||||
Navigator.pushNamed(context, '/movie-detail', arguments: movie);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colors = Theme.of(context).colorScheme;
|
||||
return Column(
|
||||
final isWideContent = Breakpoint.isWideContent(context);
|
||||
final provider = context.watch<AppProvider>();
|
||||
|
||||
final masterContent = Column(
|
||||
children: [
|
||||
const MovieStatusBar(),
|
||||
Divider(height: 0.5, thickness: 0.5, color: colors.outline),
|
||||
Divider(height: 0.5, thickness: 0.5, color: colors.outlineVariant),
|
||||
Expanded(child: _buildBody(context)),
|
||||
],
|
||||
);
|
||||
|
||||
if (!isWideContent) return masterContent;
|
||||
|
||||
final selectedMovie = provider.selectedMovie;
|
||||
return MasterDetailScaffold(
|
||||
master: masterContent,
|
||||
detail: selectedMovie != null
|
||||
? MovieDetailPage(movie: selectedMovie, embedded: true)
|
||||
: const DetailPlaceholder(icon: Icons.movie_outlined, message: '选择一部影片查看详情'),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBody(BuildContext context) {
|
||||
@@ -166,16 +191,28 @@ class _MovieTabPageState extends State<MovieTabPage> {
|
||||
}
|
||||
|
||||
Widget _buildGridView() {
|
||||
return GridView.builder(
|
||||
controller: _scrollController,
|
||||
padding: const EdgeInsets.fromLTRB(16, 16, 16, 100),
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 3, childAspectRatio: 0.55, crossAxisSpacing: 12, mainAxisSpacing: 16,
|
||||
),
|
||||
itemCount: _items.length + (_hasMore ? 1 : 0),
|
||||
itemBuilder: (context, index) {
|
||||
if (index >= _items.length) return _buildLoadMoreIndicator();
|
||||
return MovieListItem(movie: _items[index]);
|
||||
return LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final crossAxisCount = responsiveCrossAxisCount(constraints.maxWidth, minItemWidth: 110);
|
||||
final isWideContent = Breakpoint.isWideContent(context);
|
||||
final provider = context.read<AppProvider>();
|
||||
return GridView.builder(
|
||||
controller: _scrollController,
|
||||
padding: const EdgeInsets.fromLTRB(16, 16, 16, 100),
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: crossAxisCount, childAspectRatio: 0.55, crossAxisSpacing: 12, mainAxisSpacing: 16,
|
||||
),
|
||||
itemCount: _items.length + (_hasMore ? 1 : 0),
|
||||
itemBuilder: (context, index) {
|
||||
if (index >= _items.length) return _buildLoadMoreIndicator();
|
||||
final item = _items[index];
|
||||
return MovieListItem(
|
||||
movie: item,
|
||||
selected: isWideContent && provider.selectedMovie?.id == item.id,
|
||||
onTap: () => _onMovieTap(item),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -206,7 +243,7 @@ class _MovieTabPageState extends State<MovieTabPage> {
|
||||
Widget _buildListCard(Movie movie) {
|
||||
final colors = Theme.of(context).colorScheme;
|
||||
return GestureDetector(
|
||||
onTap: () => Navigator.pushNamed(context, '/movie-detail', arguments: movie),
|
||||
onTap: () => _onMovieTap(movie),
|
||||
onLongPress: () => _showDeleteDialog(context, movie),
|
||||
child: Container(
|
||||
margin: const EdgeInsets.only(bottom: 8),
|
||||
@@ -267,7 +304,7 @@ class _MovieTabPageState extends State<MovieTabPage> {
|
||||
Widget _buildCoverCard(Movie movie) {
|
||||
final colors = Theme.of(context).colorScheme;
|
||||
return GestureDetector(
|
||||
onTap: () => Navigator.pushNamed(context, '/movie-detail', arguments: movie),
|
||||
onTap: () => _onMovieTap(movie),
|
||||
onLongPress: () => _showDeleteDialog(context, movie),
|
||||
child: Container(
|
||||
height: 200,
|
||||
|
||||
Reference in New Issue
Block a user