Flutter - Animate change on height when child of container renders Flutter - Animate change on height when child of container renders dart dart

Flutter - Animate change on height when child of container renders


In the end I just had to use AnimatedSize. It replicates exactly the animation that I want.

AnimatedSize(  vsync: this,  duration: Duration(milliseconds: 150),  curve: Curves.fastOutSlowIn,  child: Container(    child: Container(      child: !_isExpanded          ? null          : FadeTransition(opacity: animationFade, child: widget.child),    ),  ),);


You can use the AnimatedContainer for animations

class Animate extends StatefulWidget {  @override  _AnimateState createState() => _AnimateState();}class _AnimateState extends State<Animate> {  var height = 200.0;  @override  Widget build(BuildContext context) {    var size = MediaQuery.of(context).size;    return Scaffold(      body: Center(        child: AnimatedContainer(          color: Colors.amber,          duration: new Duration(milliseconds: 500),          height: height,        ),      ),      floatingActionButton: FloatingActionButton(        onPressed: () {          setState(() {            if (height == 200.0) {              height = 400.0;            } else {              height = 200.0;            }          });        },        child: Icon(Icons.settings),      ),    );  }}


I tweaked the ExpansionTile, this has proper animation. Hope this helps

class _FixedExpansionTileState extends State<FixedExpansionTile> with SingleTickerProviderStateMixin {  AnimationController _controller;  CurvedAnimation _easeOutAnimation;  CurvedAnimation _easeInAnimation;  ColorTween _borderColor;  ColorTween _headerColor;  ColorTween _iconColor;  ColorTween _backgroundColor;  Animation<double> _iconTurns;  bool _isExpanded = false;  @override  void initState() {    super.initState();    _controller = new AnimationController(duration: _kExpand, vsync: this);    _easeOutAnimation = new CurvedAnimation(parent: _controller, curve: Curves.easeOut);    _easeInAnimation = new CurvedAnimation(parent: _controller, curve: Curves.easeIn);    _borderColor = new ColorTween();    _headerColor = new ColorTween();    _iconColor = new ColorTween();    _iconTurns = new Tween<double>(begin: 0.0, end: 0.5).animate(_easeInAnimation);    _backgroundColor = new ColorTween();    _isExpanded = PageStorage.of(context)?.readState(context) ?? widget.initiallyExpanded;    if (_isExpanded)      _controller.value = 1.0;  }  @override  void dispose() {    _controller.dispose();    super.dispose();  }  void _handleTap() {    setState(() {      _isExpanded = !_isExpanded;      if (_isExpanded)        _controller.forward();      else        _controller.reverse().then<void>((value) {          setState(() {            // Rebuild without widget.children.          });        });      PageStorage.of(context)?.writeState(context, _isExpanded);    });    if (widget.onExpansionChanged != null)      widget.onExpansionChanged(_isExpanded);  }  Widget _buildChildren(BuildContext context, Widget child) {    final Color borderSideColor =  Colors.transparent;  //  final Color titleColor = _headerColor.evaluate(_easeInAnimation);    return new Container(      decoration: new BoxDecoration(        color: _backgroundColor.evaluate(_easeOutAnimation) ?? Colors.transparent,        border: new Border(          top: new BorderSide(color: borderSideColor),          bottom: new BorderSide(color: borderSideColor),        )      ),      child: new Column(        mainAxisSize: MainAxisSize.min,        children: <Widget>[          IconTheme.merge(            data: new IconThemeData(color: _iconColor.evaluate(_easeInAnimation)),            child: new ListTile(              onTap: _handleTap,              leading: widget.leading,              title: new DefaultTextStyle(                style: Theme.of(context).textTheme.subhead.copyWith(color: Colors.transparent),                child: widget.title,              ),              trailing: widget.trailing ?? new RotationTransition(                turns: _iconTurns,                child: const Icon(Icons.expand_more),              ),            ),          ),          new ClipRect(            child: new Align(              heightFactor: _easeInAnimation.value,              child: child,            ),          ),        ],      ),    );  }  @override  Widget build(BuildContext context) {    final ThemeData theme = Theme.of(context);    _borderColor.end = theme.dividerColor;    _headerColor      ..begin = theme.textTheme.subhead.color      ..end = theme.accentColor;    _iconColor      ..begin = theme.unselectedWidgetColor      ..end = theme.accentColor;    _backgroundColor.end = widget.backgroundColor;    final bool closed = !_isExpanded && _controller.isDismissed;    return new AnimatedBuilder(      animation: _controller.view,      builder: _buildChildren,      child: closed ? null : new Column(children: widget.children),    );  }}