Flutter 如何在颤振中设置塌陷元素的动画

Flutter 如何在颤振中设置塌陷元素的动画,flutter,dart,flutter-layout,Flutter,Dart,Flutter Layout,当用户使用动画点击不同的小部件(同级或父级)时,如何展开和折叠小部件 new Column( children: <Widget>[ new header.IngridientHeader( new Icon( Icons.fiber_manual_record, color: AppColors.primaryColor ),

当用户使用动画点击不同的小部件(同级或父级)时,如何展开和折叠小部件

new Column(
    children: <Widget>[
        new header.IngridientHeader(
            new Icon(
                Icons.fiber_manual_record,
                color: AppColors.primaryColor
            ),
            'Voice Track 1'
        ),
        new Grid()
    ],
)
新列(
儿童:[
新页眉.IngridientHeader(
新图标(
Icons.fiber\u手动\u记录,
颜色:AppColors.primaryColor
),
“音轨1”
),
新网格()
],
)
我希望用户能够点击header.IngridientHeader,然后网格小部件应该切换(如果可见则隐藏,反之亦然)

编辑:

我试图做一些在引导中被称为崩溃的事情

编辑2: header.IngridientHeader应始终保持在位
Grid()是可滚动(水平)的小部件。

我想您正在寻找小部件。这需要一个
title
属性,该属性相当于header和
children
属性,您可以将切换时显示或隐藏的小部件传递到该属性。 你可以找到一个如何使用它的例子

简单示例用法:

new ExpansionTile(title: new Text("Numbers"),
      children: <Widget>[
        new Text("Number: 1"),
        new Text("Number: 2"),
        new Text("Number: 3"),
        new Text("Number: 4"),
        new Text("Number: 5")
      ],
),
新扩展文件(标题:新文本(“数字”),
儿童:[
新文本(“编号:1”),
新文本(“编号:2”),
新文本(“编号:3”),
新文本(“编号:4”),
新文本(“编号:5”)
],
),

希望有帮助

或者,您可以使用一个来模拟这种行为

class AnimateContentExample扩展StatefulWidget{
@凌驾
_AnimateContentExampleState createState()=>new_AnimateContentExampleState();
}
类_AnimateContentExampleState扩展状态{
double _animatedHeight=100.0;
@凌驾
小部件构建(构建上下文){
归还新脚手架(
appBar:new appBar(标题:新文本(“动画内容”),),
正文:新栏目(
儿童:[
新卡(
子:新列(
mainAxisAlignment:mainAxisAlignment.center,
crossAxisAlignment:crossAxisAlignment.center,
儿童:[
新手势检测器(
onTap:()=>设置状态(){
_animatedHeight!=0.0?_animatedHeight=0.0:_animatedHeight=100.0;}),
子容器:新容器(
子项:新文本(“单击我”),
颜色:Colors.blueAccent,
身高:25.0,
宽度:100.0,
),),
新的AnimatedContainer(持续时间:const持续时间(毫秒:120),
子项:新文本(“切换我”),
高度:_动画高度,
颜色:Colors.tealacent,
宽度:100.0,
)
],
) ,
)
],
),
);
}
}

如果要将小部件折叠为零高度或零宽度,并且折叠时子部件会溢出,我建议使用或

下面是一个ScaleTransition小部件的示例,该小部件用于折叠四个黑色按钮和状态文本的容器。MyExpandedSection小部件与列一起使用,以获得以下结构。

与SizeTransition小部件一起使用动画的小部件示例:

class ExpandedSection扩展StatefulWidget{
最后一个孩子;
最终布尔展开;
ExpandedSection({this.expand=false,this.child});
@凌驾
_ExpandedSectionState createState()=>\u ExpandedSectionState();
}
类_ExpandedSectionState使用SingleTickerProviderStateMixin扩展状态{
动画控制器;
动画;
@凌驾
void initState(){
super.initState();
准备活动();
_runExpandCheck();
}
///设置动画
无效准备活动(){
expandController=动画控制器(
vsync:这个,,
持续时间:持续时间(毫秒:500)
);
动画=曲线动画(
父:expandController,
曲线:Curves.FastOutSwowin,
);
}
void_runExpandCheck(){
if(widget.expand){
expandController.forward();
}
否则{
expandController.reverse();
}
}
@凌驾
void didUpdateWidget(ExpandedSection oldWidget){
super.didUpdateWidget(oldWidget);
_runExpandCheck();
}
@凌驾
无效处置(){
expandController.dispose();
super.dispose();
}
@凌驾
小部件构建(构建上下文){
返回大小转换(
axisAlignment:1.0,
sizeFactor:动画,
child:widget.child
);
}
}

也可以工作,但如果子对象不能调整为零宽度或零高度,flifter可能会抱怨溢出

输出:


代码:

类FooPageState扩展状态{
静态常数持续时间=持续时间(秒:1);
int _flex1=1,_flex2=2,_flex3=1;
@凌驾
小部件构建(构建上下文){
最终总数=_flex1+_flex2+_flex3;
最终高度=MediaQuery.of(context).size.height;
最终高度1=(高度*1)/总高度;
最终高度2=(高度*2)/总高度;
最终高度3=(高度*_flex3)/总高度;
返回脚手架(
正文:专栏(
儿童:[
动画容器(
高度:高度1,
持续时间:_持续时间,
颜色:颜色,红色,
),
动画容器(
高度:高度2,
持续时间:_持续时间,
颜色:颜色。绿色,
),
动画容器(
高度:高度3,
持续时间:_持续时间,
颜色:颜色,蓝色,
),
],
),
);
}
}

多亏了@Adam Jonsson,他的回答解决了我的问题。这是关于如何使用ExpandedSection的演示,希望对您有所帮助

class ExpandedSection扩展StatefulWidget{
最后一个孩子;
最终布尔展开;
ExpandedSection({this.expand=false,this.child});
@凌驾
_ExpandedSectionState createState()=>\u Expa
class AnimateContentExample extends StatefulWidget {
  @override
  _AnimateContentExampleState createState() => new _AnimateContentExampleState();
}

class _AnimateContentExampleState extends State<AnimateContentExample> {
  double _animatedHeight = 100.0;
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(title: new Text("Animate Content"),),
      body: new Column(
        children: <Widget>[
          new Card(
            child: new Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: <Widget>[
                new GestureDetector(
                  onTap: ()=>setState((){
                    _animatedHeight!=0.0?_animatedHeight=0.0:_animatedHeight=100.0;}),
                  child:  new Container(
                  child: new Text("CLICK ME"),
                  color: Colors.blueAccent,
                  height: 25.0,
                    width: 100.0,
                ),),
                new AnimatedContainer(duration: const Duration(milliseconds: 120),
                  child: new Text("Toggle Me"),
                  height: _animatedHeight,
                  color: Colors.tealAccent,
                  width: 100.0,
                )
              ],
            ) ,
          )
        ],
      ),
    );
  }
}
class ExpandedSection extends StatefulWidget {

  final Widget child;
  final bool expand;
  ExpandedSection({this.expand = false, this.child});

  @override
  _ExpandedSectionState createState() => _ExpandedSectionState();
}

class _ExpandedSectionState extends State<ExpandedSection> with SingleTickerProviderStateMixin {
  AnimationController expandController;
  Animation<double> animation; 

  @override
  void initState() {
    super.initState();
    prepareAnimations();
    _runExpandCheck();
  }

  ///Setting up the animation
  void prepareAnimations() {
    expandController = AnimationController(
      vsync: this,
      duration: Duration(milliseconds: 500)
    );
    animation = CurvedAnimation(
      parent: expandController,
      curve: Curves.fastOutSlowIn,
    );
  }

  void _runExpandCheck() {
    if(widget.expand) {
      expandController.forward();
    }
    else {
      expandController.reverse();
    }
  }

  @override
  void didUpdateWidget(ExpandedSection oldWidget) {
    super.didUpdateWidget(oldWidget);
    _runExpandCheck();
  }

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

  @override
  Widget build(BuildContext context) {
    return SizeTransition(
      axisAlignment: 1.0,
      sizeFactor: animation,
      child: widget.child
    );
  }
}