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

Flutter Container高度动画从中间启动,需改为从底部启动求解决方案

解决Flutter容器高度动画从底部启动的问题

嘿,这个问题我熟!默认情况下直接给Container做高度动画时,容器会基于父布局的中心对齐,所以高度变化时是上下同时延伸的。要改成从底部启动(也就是底部固定,高度向上扩展),有两个简单好用的方案,我结合你的代码给你演示下:

方案一:用Align组件固定底部对齐

这种方法最直观,把你的动画容器放在Align里,设置对齐方式为Alignment.bottomCenter,这样容器的底部会固定在父容器的底部,高度增加时只会向上扩展:

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

class CorrectWrongOverlay extends StatefulWidget {
  final bool _isCorrect;
  final VoidCallback _onTap;
  final double percentR;
  final double percentW;

  CorrectWrongOverlay(
    this._isCorrect,
    this.percentR,
    this.percentW,
    this._onTap,
  );

  @override
  State createState() => CorrectWrongOverlayState();
}

class CorrectWrongOverlayState extends State<CorrectWrongOverlay> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _heightAnimation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(milliseconds: 600),
      vsync: this,
    );
    // 这里假设你要动画到屏幕高度的percentR比例
    _heightAnimation = Tween<double>(
      begin: 0,
      end: MediaQuery.of(context).size.height * widget.percentR,
    ).animate(CurvedAnimation(parent: _controller, curve: Curves.easeOut));
    _controller.forward(); // 启动动画
  }

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

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: widget._onTap,
      child: Container(
        color: Colors.black54, // 半透明背景
        child: Align(
          alignment: Alignment.bottomCenter, // 关键:固定底部对齐
          child: AnimatedBuilder(
            animation: _heightAnimation,
            builder: (context, child) {
              return Container(
                height: _heightAnimation.value,
                width: MediaQuery.of(context).size.width * widget.percentW,
                color: widget._isCorrect ? Colors.green.shade700 : Colors.red.shade700,
                // 这里可以加你的图标、文字等内容
                child: Center(
                  child: Icon(
                    widget._isCorrect ? Icons.check : Icons.close,
                    size: 60,
                    color: Colors.white,
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );
  }
}

方案二:用SizeTransition组件(更简洁)

Flutter自带的SizeTransition组件专门处理尺寸动画,其中axisAlignment参数可以直接控制动画的起始位置:

  • axisAlignment: 1.0 代表垂直方向从底部开始动画
  • axisAlignment: 0.0 是默认的中心动画
  • axisAlignment: -1.0 是从顶部开始动画

代码示例:

// 其他部分和上面的State代码一致,只修改build里的内容
@override
Widget build(BuildContext context) {
  return GestureDetector(
    onTap: widget._onTap,
    child: Container(
      color: Colors.black54,
      child: Center(
        child: SizeTransition(
          sizeFactor: _heightAnimation,
          axisAlignment: 1.0, // 关键:设置为1.0从底部启动
          axis: Axis.vertical, // 垂直方向的尺寸动画
          child: Container(
            width: MediaQuery.of(context).size.width * widget.percentW,
            color: widget._isCorrect ? Colors.green.shade700 : Colors.red.shade700,
            child: Center(
              child: Icon(
                widget._isCorrect ? Icons.check : Icons.close,
                size: 60,
                color: Colors.white,
              ),
            ),
          ),
        ),
      ),
    ),
  );
}

两种方案都能实现你要的效果,选哪个看你的习惯:Align更直观,SizeTransition是官方专门的动画组件,代码更简洁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 04:08:45