如何在Flutter中实现该页面滑动交互效果?
Flutter实现右侧左滑过半跳转页面效果
核心实现思路
- 通过
GestureDetector监听水平拖动事件,实时记录页面偏移量 - 利用
Transform.translate配合动画,实现页面跟随拖动的位移效果 - 拖动结束时判断偏移量是否超过屏幕宽度的一半,决定跳转到新页面或回弹至原位置
完整代码示例
import 'package:flutter/material.dart'; class SwipeToNavigatePage extends StatefulWidget { const SwipeToNavigatePage({super.key}); @override State<SwipeToNavigatePage> createState() => _SwipeToNavigatePageState(); } class _SwipeToNavigatePageState extends State<SwipeToNavigatePage> with SingleTickerProviderStateMixin { late AnimationController _animationController; late Animation<double> _offsetAnimation; double _dragOffset = 0.0; late double _screenWidth; @override void initState() { super.initState(); _animationController = AnimationController( vsync: this, duration: const Duration(milliseconds: 300), ); } @override void didChangeDependencies() { super.didChangeDependencies(); _screenWidth = MediaQuery.of(context).size.width; } @override void dispose() { _animationController.dispose(); super.dispose(); } void _handleDragUpdate(DragUpdateDetails details) { setState(() { // 限制仅向左拖动,偏移量范围控制在0到-屏幕宽度之间 _dragOffset = details.localPosition.dx - _screenWidth; _dragOffset = _dragOffset.clamp(-_screenWidth, 0.0); }); } void _handleDragEnd(DragEndDetails details) { if (_dragOffset.abs() > _screenWidth / 2) { // 滑出屏幕后跳转新页面 _offsetAnimation = Tween<double>(begin: _dragOffset, end: -_screenWidth).animate(_animationController); _animationController.forward().then((_) { Navigator.push(context, MaterialPageRoute(builder: (context) => const NewPage())); _animationController.reset(); setState(() => _dragOffset = 0.0); }); } else { // 回弹至原位置 _offsetAnimation = Tween<double>(begin: _dragOffset, end: 0.0).animate(_animationController); _animationController.forward().then((_) { _animationController.reset(); setState(() => _dragOffset = 0.0); }); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('可左滑跳转页面')), body: GestureDetector( onHorizontalDragUpdate: _handleDragUpdate, onHorizontalDragEnd: _handleDragEnd, child: AnimatedBuilder( animation: _offsetAnimation, builder: (context, child) { final currentOffset = _animationController.isAnimating ? _offsetAnimation.value : _dragOffset; return Transform.translate( offset: Offset(currentOffset, 0), child: child, ); }, child: Container( width: double.infinity, padding: const EdgeInsets.all(16), child: const Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text('从右侧向左拖动页面'), SizedBox(height: 20), Text('拖动超过屏幕一半后松开,即可跳转至新页面'), ], ), ), ), ), ); } } class NewPage extends StatelessWidget { const NewPage({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('新页面')), body: const Center(child: Text('这是跳转后的新页面')), ); } }
关键代码说明
- 拖动监听:
GestureDetector的onHorizontalDragUpdate实时更新页面偏移量,onHorizontalDragEnd处理拖动结束后的逻辑 - 动画过渡:
AnimationController配合Tween实现回弹和滑出的平滑动画,避免生硬的位移变化 - 跳转判断:通过对比偏移量绝对值与屏幕宽度的一半,决定是触发页面跳转还是回弹
内容的提问来源于stack exchange,提问作者ThatKid
相关产品推荐
相关产品推荐

