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

Flutter问题:实现按钮后方滑入的Bottom Sheet动画

修复Bottom Sheet从屏幕底部滑入的动画问题

你的问题核心在于两点:一是用AnimatedSize仅改变容器高度,导致视图向上扩展而非从底部滑入;二是将触发按钮嵌套在Bottom Sheet内部,按钮位置会随Bottom Sheet尺寸变化而移动。以下是具体修复方案:

核心改动思路

  • 放弃Scaffold的bottomSheet属性,改用手动布局控制Bottom Sheet初始位置,确保其完全隐藏在屏幕下方
  • 使用平移动画替代尺寸变化动画,实现从屏幕底部滑入的效果
  • 将触发按钮固定在屏幕底部最上层,与Bottom Sheet的动画状态解耦

修复后的完整代码

import 'package:flutter/material.dart';

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

  @override
  State<BottomSheetExample> createState() => _BottomSheetExampleState();
}

class _BottomSheetExampleState extends State<BottomSheetExample> {
  bool _isSheetExpanded = false;
  final double _sheetHeight = 200;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.green,
      body: const Center(child: Text('Body')),
      // 固定触发按钮在屏幕底部最上层
      floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
      floatingActionButton: ElevatedButton(
        onPressed: () => setState(() => _isSheetExpanded = !_isSheetExpanded),
        child: const Text("Toggle"),
      ),
      // 用AnimatedContainer实现滑入动画
      bottomNavigationBar: AnimatedContainer(
        duration: const Duration(milliseconds: 500),
        curve: Curves.easeInOut,
        // 初始时将Bottom Sheet移出屏幕,展开时复位
        transform: Matrix4.translationValues(0, _isSheetExpanded ? 0 : _sheetHeight, 0),
        height: _sheetHeight,
        child: Container(
          color: Colors.amber,
          padding: const EdgeInsets.all(20),
          child: const Center(child: Text('Bottom Sheet')),
        ),
      ),
    );
  }
}

代码说明

  1. 动画逻辑:通过AnimatedContainer的transform属性控制Y轴位移,初始状态下Bottom Sheet完全位于屏幕下方,展开时位移归零,实现从底部滑入的自然动画
  2. 按钮独立:将按钮放在floatingActionButton并设置centerFloat位置,始终固定在屏幕底部最上层,不会随Bottom Sheet移动
  3. 状态控制:用_isSheetExpanded布尔值切换展开/收起状态,动画时长和曲线可根据需求调整

如果偏好使用SlideTransition实现动画,可替换bottomNavigationBar部分为以下代码(需混入SingleTickerProviderStateMixin):

bottomNavigationBar: SlideTransition(
  position: Tween<Offset>(
    begin: const Offset(0, 1), // 初始在屏幕外(下方)
    end: const Offset(0, 0), // 展开时回到屏幕底部
  ).animate(CurvedAnimation(
    parent: AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 500),
    )..forward(from: _isSheetExpanded ? 1 : 0),
    curve: Curves.easeInOut,
  )),
  child: Container(
    height: _sheetHeight,
    color: Colors.amber,
    padding: const EdgeInsets.all(20),
    child: const Center(child: Text('Bottom Sheet')),
  ),
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 11:05:22