You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中如何通过拖动容器实现逐步滑动导航到新页面的效果

实现方案

你需要实现的这个上滑拖拽跳转交互,不用直接调用原生Navigator.push,可以先在当前页面的Stack层叠加NewPage做跟随动画,动画完成后再执行跳转补全路由栈,避免路由栈逻辑混乱。

第一步:新增状态变量

在_MainPageState中定义以下变量:

// 设备屏幕高度
double _screenHeight = 0;
// 拖拽偏移量,向上拖拽时为负值
double _dragOffset = 0;
// 控制是否展示拖拽态的NewPage
bool _isShowDragPage = false;
// 跳转触发阈值,拖拽超过屏幕30%高度就触发跳转
final double _dragThreshold = 0.3;
// 补间动画控制器
late AnimationController _animationController;

第二步:初始化与销毁逻辑

在生命周期方法中完成变量的初始化和回收:

@override
void initState() {
  super.initState();
  WidgetsBinding.instance.addPostFrameCallback((_) {
    _screenHeight = MediaQuery.of(context).size.height;
  });
  _animationController = AnimationController(vsync: this, duration: const Duration(milliseconds: 200));
}

@override
void dispose() {
  _animationController.dispose();
  super.dispose();
}

第三步:修改Stack布局,叠加NewPage层

调整你现有代码的Stack结构,补充手势回调和NewPage的跟随逻辑:

Stack(
  children: [
    // 原有主页面的其他内容
    ...
    // 原有可拖拽Container的逻辑改造
    Positioned(
      // 原有top值加上拖拽偏移量,实现Container跟随手势移动
      top: _yourOriginalTop + _dragOffset,
      child: GestureDetector(
        onVerticalDragStart: (details) {
          // 拖拽开始,标记展示NewPage层
          setState(() {
            _isShowDragPage = true;
          });
        },
        onVerticalDragUpdate: (details) {
          // 仅响应向上拖拽的手势
          if (details.delta.dy < 0) {
            setState(() {
              _dragOffset += details.delta.dy;
            });
          }
        },
        onVerticalDragEnd: (details) async {
          // 计算当前拖拽距离占屏幕的比例
          double dragProportion = _dragOffset.abs() / _screenHeight;
          if (dragProportion >= _dragThreshold) {
            // 超过阈值,执行动画让NewPage铺满全屏
            _animationController.forward();
            setState(() {
              _dragOffset = -_screenHeight;
            });
            // 动画结束后执行正式路由跳转
            await Future.delayed(const Duration(milliseconds: 200));
            if (mounted) {
              // 关闭路由默认跳转动画,避免和自定义动画冲突
              Navigator.push(context, PageRouteBuilder(
                pageBuilder: (context, animation, secondaryAnimation) => const NewPage(),
                transitionDuration: Duration.zero,
              ));
              // 重置状态
              setState(() {
                _isShowDragPage = false;
                _dragOffset = 0;
              });
            }
          } else {
            // 未超过阈值,回弹复位
            setState(() {
              _dragOffset = 0;
              _isShowDragPage = false;
            });
          }
        },
        child: Container(/* 原有Container的配置 */),
      ),
    ),
    // 叠加在顶层的NewPage,仅拖拽状态下展示
    if (_isShowDragPage) Positioned(
      top: _screenHeight + _dragOffset,
      left: 0,
      right: 0,
      height: _screenHeight,
      // 可添加Opacity实现NewPage随拖拽进度渐显的效果
      child: Opacity(
        opacity: (_dragOffset.abs() / (_screenHeight * _dragThreshold)).clamp(0, 1),
        child: const NewPage(),
      ),
    )
  ],
)

内容的提问来源于stack exchange,提问作者mms59

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 23:15:07