Flutter中如何修改iOS端的侧滑返回手势滑动方向
Flutter实现iOS端右边缘左滑返回的方案
Flutter自带的CupertinoPageRoute默认仅支持左边缘右滑触发返回,只需自定义路由逻辑替换手势识别规则即可实现反向侧滑返回。
1. 自定义支持右滑返回的路由类
直接继承CupertinoPageRoute,重写手势检测逻辑,将触发区域改为右边缘,滑动方向改为左滑:
import 'package:flutter/cupertino.dart'; import 'package:flutter/gestures.dart'; class RightBackCupertinoRoute<T> extends CupertinoPageRoute<T> { RightBackCupertinoRoute({ required super.builder, super.settings, super.maintainState = true, super.fullscreenDialog = false, }); @override Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) { // 全屏弹窗保持原生逻辑,不添加右滑返回 if (fullscreenDialog) { return super.buildTransitions(context, animation, secondaryAnimation, child); } return _RightBackGestureWrapper( route: this, child: super.buildTransitions(context, animation, secondaryAnimation, child), ); } } class _RightBackGestureWrapper extends StatefulWidget { const _RightBackGestureWrapper({required this.route, required this.child}); final CupertinoPageRoute route; final Widget child; @override State<_RightBackGestureWrapper> createState() => _RightBackGestureWrapperState(); } class _RightBackGestureWrapperState extends State<_RightBackGestureWrapper> { late HorizontalDragGestureRecognizer _dragRecognizer; @override void initState() { super.initState(); _dragRecognizer = HorizontalDragGestureRecognizer(debugOwner: this) ..onStart = _onDragStart ..onUpdate = _onDragUpdate ..onEnd = _onDragEnd ..onCancel = _onDragCancel; } @override void dispose() { _dragRecognizer.dispose(); super.dispose(); } /// 仅响应右边缘20dp范围内的触摸 bool _isValidTouch(Offset localPos) { return localPos.dx > MediaQuery.of(context).size.width - 20; } void _onDragStart(DragStartDetails details) { if (!_isValidTouch(details.localPosition)) return; widget.route.didStartUserGesture(); } void _onDragUpdate(DragUpdateDetails details) { if (!widget.route.popGestureIsActive) return; // 左滑时减小动画值,对应页面向左滑出的效果 widget.route.controller!.value -= details.primaryDelta! / MediaQuery.of(context).size.width; } void _onDragEnd(DragEndDetails details) { if (!widget.route.popGestureIsActive) return; // 滑动速度超过阈值/滑动距离超过页面一半即触发返回 const minSwipeVelocity = 365.0; final swipeSpeed = details.velocity.pixelsPerSecond.dx.abs(); if (swipeSpeed > minSwipeVelocity || widget.route.controller!.value < 0.5) { widget.route.navigator?.pop(); } else { widget.route.controller!.forward(); } widget.route.didStopUserGesture(); } void _onDragCancel() { if (widget.route.popGestureIsActive) { widget.route.didStopUserGesture(); } } @override Widget build(BuildContext context) { return Stack( children: [ widget.child, Positioned.fill( child: Listener( onPointerDown: (event) { if (widget.route.popGestureEnabled && _isValidTouch(event.localPosition)) { _dragRecognizer.addPointer(event); } }, ), ), ], ); } }
2. 路由使用方式
单页面跳转替换
跳转页面时直接用自定义路由替换默认的CupertinoPageRoute即可:
Navigator.push( context, RightBackCupertinoRoute( builder: (context) => const TargetPage(), ), );
全局生效配置
在根组件的onGenerateRoute中统一配置,所有页面自动支持右滑返回:
CupertinoApp( // 其他配置省略 onGenerateRoute: (settings) { switch (settings.name) { case '/home': return RightBackCupertinoRoute( builder: (context) => const HomePage(), settings: settings, ); case '/detail': return RightBackCupertinoRoute( builder: (context) => const DetailPage(), settings: settings, ); default: return RightBackCupertinoRoute( builder: (context) => const HomePage(), settings: settings, ); } }, )
可选调整项
- 修改代码中
20的数值,可自定义右边缘手势响应区域的宽度 - 调整
minSwipeVelocity的数值,可修改触发返回需要的最小滑动速度
内容的提问来源于stack exchange,提问作者Ardeshir ojan
相关产品推荐
相关产品推荐

