generated from dellevin/template
1
This commit is contained in:
@@ -41,6 +41,8 @@ class _MovieTabPageState extends State<MovieTabPage> {
|
|||||||
int _prevDisplayMode = -1;
|
int _prevDisplayMode = -1;
|
||||||
int _prevSortMode = -1;
|
int _prevSortMode = -1;
|
||||||
double _swipeOffset = 0.0; // 当前拖动偏移量(用于左右滑动切换状态)
|
double _swipeOffset = 0.0; // 当前拖动偏移量(用于左右滑动切换状态)
|
||||||
|
int _direction = 1; // 翻页方向:+1 新页从右滑入,-1 新页从左滑入
|
||||||
|
int _prevTabIndex = -1; // 上一次的标签索引,用于计算翻页方向
|
||||||
|
|
||||||
static const _statusMap = {0: 'watched', 1: 'watching', 2: 'want_to_watch'};
|
static const _statusMap = {0: 'watched', 1: 'watching', 2: 'want_to_watch'};
|
||||||
|
|
||||||
@@ -264,6 +266,17 @@ class _MovieTabPageState extends State<MovieTabPage> {
|
|||||||
);
|
);
|
||||||
}();
|
}();
|
||||||
|
|
||||||
|
// 当前标签索引(分类模式或观看状态模式)
|
||||||
|
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 包裹,左右滑动切换状态/分类
|
// 用 GestureDetector 包裹,左右滑动切换状态/分类
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onHorizontalDragStart: (_) => _swipeOffset = 0.0,
|
onHorizontalDragStart: (_) => _swipeOffset = 0.0,
|
||||||
@@ -288,14 +301,35 @@ class _MovieTabPageState extends State<MovieTabPage> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: TweenAnimationBuilder<double>(
|
child: TweenAnimationBuilder<double>(
|
||||||
tween: Tween(begin: 0.0, end: _swipeOffset.clamp(-100.0, 100.0)),
|
tween: Tween(begin: 0.0, end: _swipeOffset.clamp(-80.0, 80.0)),
|
||||||
duration: const Duration(milliseconds: 150),
|
duration: const Duration(milliseconds: 120),
|
||||||
curve: Curves.easeOut,
|
curve: Curves.easeOut,
|
||||||
builder: (context, value, child) {
|
builder: (context, value, child) {
|
||||||
return Transform.translate(offset: Offset(value, 0), child: child);
|
return Transform.translate(offset: Offset(value, 0), child: child);
|
||||||
},
|
},
|
||||||
|
child: AnimatedSwitcher(
|
||||||
|
duration: const Duration(milliseconds: 300),
|
||||||
|
switchInCurve: Curves.easeOutCubic,
|
||||||
|
switchOutCurve: Curves.easeInCubic,
|
||||||
|
transitionBuilder: (child, animation) {
|
||||||
|
// 新页从滑动方向滑入,旧页朝反向滑出,形成翻页效果
|
||||||
|
final isIncoming = child.key == ValueKey<int>(currentIndex);
|
||||||
|
final dir = (isIncoming ? _direction : -_direction).toDouble();
|
||||||
|
final width = MediaQuery.of(context).size.width;
|
||||||
|
return SlideTransition(
|
||||||
|
position: Tween<Offset>(
|
||||||
|
begin: Offset(dir * width, 0),
|
||||||
|
end: Offset.zero,
|
||||||
|
).animate(animation),
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: KeyedSubtree(
|
||||||
|
key: ValueKey<int>(currentIndex),
|
||||||
child: content,
|
child: content,
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user