【问题标题】:Flutter - Animate change on height when child of container rendersFlutter - 容器子渲染时的高度动画变化
【发布时间】:2019-05-15 01:19:26
【问题描述】:

我正在尝试重新创建 ExpansionTile 之类的东西,但在 Card 中。当我点击卡片时,它的子元素会渲染并且卡片会改变它的高度,所以我想为这个变化制作动画。

我尝试使用 AnimatedContainerGlobalKey 来了解卡片的最终尺寸及其子渲染,然后将新高度设置为 AnimatedContainer,但这不起作用。

【问题讨论】:

    标签: dart flutter flutter-animation


    【解决方案1】:

    最后我只需要使用AnimatedSize。它完全复制了我想要的动画。

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

    【讨论】:

    • 不错的一个。当高度变大时,它会完美运行。但如果高度变小,它只会为容器周围的小部件设置动画。不是容器本身。
    • 好吧,对不起,我改变了树:现在带有背景的小部件(一个容器)是 AnimatedSize 的父级。当高度变小时,动画播放良好。
    • 在我的情况下,AnimatedSize 不起作用,所以我将 AnimatedContainer 与动态 height 属性一起使用。
    【解决方案2】:

    您可以使用 AnimatedContainer 制作动画

    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),
          ),
        );
      }
    }
    

    【讨论】:

    • 这不适用于动态内容,因为它会有不同的高度。
    【解决方案3】:

    我调整了 ExpansionTile,它有适当的动画。希望这会有所帮助

    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),
        );
    
      }
    }
    

    【讨论】:

    • 如果我理解这个,我可以使用AnimatedBuilder 来动画化孩子渲染时的高度变化吗?
    猜你喜欢
    • 1970-01-01
    • 2021-05-12
    • 1970-01-01
    • 2022-11-13
    • 1970-01-01
    • 2022-01-19
    • 2015-02-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多