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

Flutter点击FAB实现下到上动画切页、FAB旋转且底部导航固定如何实现?

Flutter FAB联动底部弹出页实现方案

核心逻辑:要保证底部导航栏无位移,不使用系统路由跳转逻辑,而是在Scaffold的Body层叠放置弹出页容器,通过自定义动画控制显隐,BottomNavigationBar始终固定在Scaffold层级不受影响。


依赖变量与动画初始化

在State类中定义以下变量,在生命周期中完成动画配置:

import 'package:flutter/material.dart';
import 'dart:math' as math;

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin {
  // 弹出页开关状态
  bool _isPanelOpen = false;
  // 动画控制器
  late AnimationController _animationController;
  // FAB旋转动画
  late Animation<double> _fabRotateAnim;
  // 弹出位移动画
  late Animation<Offset> _panelSlideAnim;
  // 背景遮罩透明度动画
  late Animation<double> _maskOpacityAnim;

  @override
  void initState() {
    super.initState();
    _animationController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 300),
    );
    // FAB从0度转到45度
    _fabRotateAnim = Tween<double>(begin: 0, end: math.pi / 4).animate(
      CurvedAnimation(parent: _animationController, curve: Curves.easeInOut),
    );
    // 弹出页从屏幕外底部滑入
    _panelSlideAnim = Tween<Offset>(begin: const Offset(0, 1), end: Offset.zero).animate(
      CurvedAnimation(parent: _animationController, curve: Curves.easeInOut),
    );
    // 背景遮罩从透明到半黑
    _maskOpacityAnim = Tween<double>(begin: 0, end: 0.5).animate(
      CurvedAnimation(parent: _animationController, curve: Curves.easeInOut),
    );
  }

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

  // FAB点击触发逻辑
  void _togglePanel() {
    if (_isPanelOpen) {
      _animationController.reverse();
    } else {
      _animationController.forward();
    }
    setState(() {
      _isPanelOpen = !_isPanelOpen;
    });
  }

页面结构实现

Scaffold结构中BottomNavigationBar正常配置,Body用Stack层叠原有页面、遮罩、弹出页三层:

@override
  Widget build(BuildContext context) {
    return Scaffold(
      // 底部导航栏固定在Scaffold层级,不会受弹出页动画影响
      bottomNavigationBar: BottomNavigationBar(
        items: const [
          BottomNavigationBarItem(icon: Icon(Icons.home), label: "首页"),
          BottomNavigationBarItem(icon: Icon(Icons.person), label: "我的"),
        ],
      ),
      floatingActionButton: AnimatedBuilder(
        animation: _fabRotateAnim,
        builder: (context, child) => Transform.rotate(
          angle: _fabRotateAnim.value,
          child: FloatingActionButton(
            onPressed: _togglePanel,
            child: const Icon(Icons.add),
          ),
        ),
      ),
      body: Stack(
        children: [
          // 第一层:原有页面内容
          const Center(child: Text("原有页面内容")),
          // 第二层:半透明遮罩,点击也可关闭弹出页
          AnimatedBuilder(
            animation: _maskOpacityAnim,
            builder: (context, child) => _maskOpacityAnim.value > 0
                ? GestureDetector(
                    onTap: _togglePanel,
                    child: Container(
                      width: double.infinity,
                      height: double.infinity,
                      color: Colors.black.withOpacity(_maskOpacityAnim.value),
                    ),
                  )
                : const SizedBox.shrink(),
          ),
          // 第三层:底部弹出页
          AnimatedBuilder(
            animation: _panelSlideAnim,
            builder: (context, child) => Transform.translate(
              offset: _panelSlideAnim.value,
              child: Align(
                alignment: Alignment.bottomCenter,
                child: Container(
                  width: double.infinity,
                  height: MediaQuery.of(context).size.height * 0.75,
                  color: Colors.white,
                  // 此处可替换为你需要的弹出页内容
                  child: const Center(child: Text("弹出页内容")),
                ),
              ),
            ),
          )
        ],
      ),
    );
  }
}

效果验证

  • FAB默认显示+号图标,点击后平滑旋转45度变成×号样式,再次点击恢复原状
  • 弹出页从底部平滑滑入,滑出过程中底部导航栏全程保持原位无位移
  • 点击半透明遮罩也可触发关闭逻辑,可根据需求自行删减该交互

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 21:06:06