From 43d8c01bb2a981514caaaf5bfe97e892c71a66fd Mon Sep 17 00:00:00 2001 From: DelLevin-Home Date: Wed, 12 Aug 2026 20:03:22 +0800 Subject: [PATCH] 1 --- lib/pages/movies/movie_tab_page.dart | 40 +++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/lib/pages/movies/movie_tab_page.dart b/lib/pages/movies/movie_tab_page.dart index a16cd28..fbee7ff 100644 --- a/lib/pages/movies/movie_tab_page.dart +++ b/lib/pages/movies/movie_tab_page.dart @@ -41,6 +41,8 @@ class _MovieTabPageState extends State { int _prevDisplayMode = -1; int _prevSortMode = -1; double _swipeOffset = 0.0; // 当前拖动偏移量(用于左右滑动切换状态) + int _direction = 1; // 翻页方向:+1 新页从右滑入,-1 新页从左滑入 + int _prevTabIndex = -1; // 上一次的标签索引,用于计算翻页方向 static const _statusMap = {0: 'watched', 1: 'watching', 2: 'want_to_watch'}; @@ -264,6 +266,17 @@ class _MovieTabPageState extends State { ); }(); + // 当前标签索引(分类模式或观看状态模式) + final currentIndex = + provider.movieDisplayMode == 1 ? provider.movieCategoryIndex : provider.movieStatusIndex; + // 计算翻页方向(用于动画):根据新旧索引的最短路径 + if (_prevTabIndex != -1 && currentIndex != _prevTabIndex) { + final count = provider.movieDisplayMode == 1 ? MovieCategoryBar.count : 3; + final raw = currentIndex - _prevTabIndex; + _direction = raw.abs() <= count / 2 ? raw.sign : -raw.sign; + } + _prevTabIndex = currentIndex; + // 用 GestureDetector 包裹,左右滑动切换状态/分类 return GestureDetector( onHorizontalDragStart: (_) => _swipeOffset = 0.0, @@ -288,13 +301,34 @@ class _MovieTabPageState extends State { } }, child: TweenAnimationBuilder( - tween: Tween(begin: 0.0, end: _swipeOffset.clamp(-100.0, 100.0)), - duration: const Duration(milliseconds: 150), + tween: Tween(begin: 0.0, end: _swipeOffset.clamp(-80.0, 80.0)), + duration: const Duration(milliseconds: 120), curve: Curves.easeOut, builder: (context, value, child) { return Transform.translate(offset: Offset(value, 0), child: child); }, - child: content, + child: AnimatedSwitcher( + duration: const Duration(milliseconds: 300), + switchInCurve: Curves.easeOutCubic, + switchOutCurve: Curves.easeInCubic, + transitionBuilder: (child, animation) { + // 新页从滑动方向滑入,旧页朝反向滑出,形成翻页效果 + final isIncoming = child.key == ValueKey(currentIndex); + final dir = (isIncoming ? _direction : -_direction).toDouble(); + final width = MediaQuery.of(context).size.width; + return SlideTransition( + position: Tween( + begin: Offset(dir * width, 0), + end: Offset.zero, + ).animate(animation), + child: child, + ); + }, + child: KeyedSubtree( + key: ValueKey(currentIndex), + child: content, + ), + ), ), ); },