Flutter小部件之AnimatedContainer

AnimatedContainer

Flutter 1.26.0-1.0.pre ,Dart 2.12.0 (build 2.12.0-141.0.dev)

简述:此处的AnimatedContainer与Container没有任何关系,它们的类关系是不同的,
AnimatedContainer->ImplicitlyAnimatedWidget->StatefulWidget->Widget,

Container->StatelessWidget->Widget.

AnimatedContainer继承自StatefulWidget,返回了一个Container部件。它们共享很多属性,AnimatedContainer在属性变化时都会呈现渐变的效果。

属性 释义
alignment → AlignmentGeometry? 在容器内对齐子部件。
child → Widget? 子部件
decoration → Decoration? 子部件后面的装饰
clipBehavior → Clip 在decoration不为空的情况下,才有效果,指定剪切的模式,
constraints → BoxConstraints? 用来约束大小,最小宽度、最大宽度、最小高度、最大高度,width和height即使设置更大的宽高也不会有效果
curve → Curve 动画运用的曲线
decoration → Decoration? 动画执行时长
foregroundDecoration → Decoration? 子部件前面的装饰
margin → EdgeInsetsGeometry? 部件的外边距
padding → EdgeInsetsGeometry? 部件的内边距
onEnd → VoidCallback? 动画执行完的回调
transform → Matrix4? 应用矩阵变换
transformAlignment → AlignmentGeometry? transform不为空时起效果,指定矩阵的原点对齐方式

示例1

在AnimatedContainer的child为null,并且不指定宽高的情况下,AnimatedContainer会铺满父控件。点击FloatingActionButton会改变AnimatedContainer的圆角半径,AnimatedContainer会呈现出渐变动画,圆角半径逐渐变化。

 AnimatedContainer(
        duration: Duration(seconds: 1),
        decoration: BoxDecoration(
          borderRadius:BorderRadius.circular( selected?200:0,),
          color: Colors.purple,
        ),
      );
animated_container_1.gif

示例2

AnimatedContainer在不指定宽高,同时不设置alignment属性的情况下,设置child不为空,AnimatedContainer会包裹住child部件,大小跟子部件一致。

 AnimatedContainer(
      duration: Duration(seconds: 1),
      decoration: BoxDecoration(
        borderRadius:BorderRadius.circular( selected?200:0,),
        color: Colors.purple,
      ),
      child:FlutterLogo(size: 100,)
    );
animated_container_2.png

示例3

AnimatedContainer在不指定宽高,child不为空,同时alignment不为空的情况下,AnimatedContainer会铺满父部件,子部件会按照AnimatedContainer的alignment排列对齐。

 AnimatedContainer(
        alignment: Alignment.center,
        duration: Duration(seconds: 1),
        decoration: BoxDecoration(
          borderRadius:BorderRadius.circular( selected?200:0,),
          color: Colors.purple,
        ),
        child:FlutterLogo(size: 100,)
    );
animated_container_3.png

示例4 属性decoration

属性decoration会在子部件后面添加一些装饰,举个小例子,添加圆角半径,圆角等于正方形边长一半时就变成了圆。
注:AnimatedContainer的color属性与decoration属性不能同时存在,decoration中含有一个color属性。关于Decoration会在后面再讲。

Center(
      child: AnimatedContainer(
          width: 200,
          height: 200,
          duration: Duration(seconds: 1),
          decoration: selected
              ? BoxDecoration(
                  borderRadius: BorderRadius.circular(100),
                  color: Colors.deepOrange[400],
                )
              : BoxDecoration(
                  borderRadius: BorderRadius.circular(0),
                  color: Colors.deepOrange[400],
                ),
          child: FlutterLogo(
            size: 100,
          )),
    );
animated_container_4.gif

示例5 属性clipBehavior

只有在decoration属性不为空的情况下,clipBehavior才有效果。clipBehavior指定的是剪切模式,例如上个例子就是对AnimatedContainer的圆角进行剪切,不同的剪切模式消耗的时间和呈现的效果都会不一样。

Clip模式:

  • Clip.none:不剪切。这是大多数小部件的默认选项:如果内容没有超出小部件边界,就不要为剪切支付任何性能成本。
  • Clip.hardEdge:剪切,不应用抗锯齿。曲线和非轴向直线会呈现锯齿状。
  • Clip.antiAlias:剪切,应用抗锯齿。该模式具有抗锯齿剪切边缘,以实现更平滑的外观。通常用来处理圆和圆弧。
  • Clip.antiAliasWithSaveLayer:应用抗锯齿,并会分配一个屏幕外缓存区。在最后被剪切和合成回来之前,所有后续的油漆都在缓冲区上执行。
    性能排序:Clip.none > Clip.hardEdge > Clip.antiAlias > Clip.antiAliasWithSaveLayer

示例6 constraints

constraints用来约束部件的宽高,即使设置更大的宽高都不会有效果。

 Center(
      child: AnimatedContainer(
          width: 200,
          height: 200,
          constraints: BoxConstraints(maxWidth: 20,maxHeight: 50),
          duration: Duration(seconds: 1),
          decoration: selected
              ? BoxDecoration(
            borderRadius: BorderRadius.circular(100),
            color: Colors.deepOrange[400],
          )
              : BoxDecoration(
            borderRadius: BorderRadius.circular(0),
            color: Colors.deepOrange[400],
          ),
          child: FlutterLogo(
            size: 100,
          )),
    );
animated_container_5.gif

示例7 curve 动画曲线

动画曲线查看

 Center(
      child: AnimatedContainer(
          width: 200,
          height: 200,
          curve: Curves.bounceOut,
          duration: Duration(seconds: 1),
          decoration: selected
              ? BoxDecoration(
            borderRadius: BorderRadius.circular(100),
            color: Colors.deepOrange[400],
          )
              : BoxDecoration(
            borderRadius: BorderRadius.circular(0),
            color: Colors.deepOrange[400],
          ),
          child: FlutterLogo(
            size: 100,
          )),
    );
  }
animated_container_6.gif

示例8 foregroundDecoration

foregroundDecoration是绘制在子部件前面的装饰,下面的例子,decoration绘制了一个黑色的背景作为子部件后面的装饰,然后在子部件前面绘制了一个红色带透明度的背景,前面的装饰会遮挡住子部件。

Center(
      child: AnimatedContainer(
          width: 200,
          height: 200,
          duration: Duration(seconds: 1),
          decoration:  BoxDecoration(
            color: Colors.black,
          ),
          foregroundDecoration: selected
              ? BoxDecoration(
            borderRadius: BorderRadius.circular(100),
            color: Colors.red.withAlpha(200),
          )
              : BoxDecoration(
            borderRadius: BorderRadius.circular(0),
            color: Colors.red.withAlpha(200),
          ),
          child: FlutterLogo(
            size: 100,
          )),
    );
  }
animated_container_7.gif

示例9 margin

Container作为父部件,AnimatedContainer作为子部件,一定要设置Container的alignment,否则AnimatedContainer会铺满Container的,

 Center(
      child: Container(
        color: Colors.black,
        width: 300,
        height: 300,
        //如果不设置alignment,AnimatedContainer会铺满父部件Container
        alignment: Alignment.topLeft,
        child: AnimatedContainer(
            width: 200,
            height: 200,
            margin: selected?EdgeInsets.only(left: 0):EdgeInsets.only(left: 50),
            color: Colors.red,
            duration: Duration(seconds: 1),
            child: FlutterLogo(
              size: 100,
            )),
      ),
    );
  }

animated_container_8.gif



如果把margin: selected?EdgeInsets.only(left: 0):EdgeInsets.only(left: 50),改成margin: selected?EdgeInsets.only(left: 0):EdgeInsets.only(left: 300)

会呈现一下效果:

animated_container_9.gif


示例10

Container作为父部件,AnimatedContainer作为子部件,一定要设置Container的alignment,否则AnimatedContainer会铺满Container的,

Center(
      child: Container(
        color: Colors.black,
        width: 300,
        height: 300,
        //如果不设置alignment,AnimatedContainer会铺满父部件Container
        alignment: Alignment.topLeft,
        child: AnimatedContainer(
            width: 200,
            height: 200,
            padding: selected?EdgeInsets.only(left: 50):EdgeInsets.only(left: 0),
            decoration:  BoxDecoration(
              color: Colors.red,
            ),
            duration: Duration(seconds: 1),
            child: FlutterLogo(
              size: 100,
            )),
      ),
    );
  }

animated_container_10.gif



如果把padding: selected?EdgeInsets.only(left: 50):EdgeInsets.only(left: 0),修改成padding: selected?EdgeInsets.only(left: 300):EdgeInsets.only(left: 0),


会呈现以下效果:

animated_container_11.gif


示例11 transform

transform是用来矩阵变换的,矩阵变换后面详细讲。这里让AnimatedContainer绕Y轴旋转

Row(
      children: [
        Expanded(flex: 1, child: Container(color: Colors.greenAccent,)),
        Expanded(
          flex: 1,
          child: Container(
            alignment: Alignment.centerLeft,
            child: AnimatedContainer(
              width: 200,
              height: 200,
              color: Colors.yellowAccent,
              transform: Matrix4.rotationY(selected ? pi : 2 * pi),
              onEnd: () {
                selected = !selected;
                setState(() {});
              },
              duration: Duration(seconds: 1),
              child: FlutterLogo(
                size: 100,
              ),
            ),
          ),
        ),
      ],
    );

animated_container_12.gif


示例12 transformAlignment

transformAlignment在transform不为空时起效果,指定矩阵原点的对齐方式。

Row(
      children: [
        Expanded(flex: 1, child: Container(color: Colors.greenAccent,)),
        Expanded(
          flex: 1,
          child: Container(
            alignment: Alignment.centerLeft,
            child: AnimatedContainer(
              width: 200,
              height: 200,
              color: Colors.yellowAccent,
              alignment: Alignment.topLeft,
              transform: Matrix4.rotationY(selected ? pi : 2 * pi),
              transformAlignment: Alignment.center,
              onEnd: () {
                selected = !selected;
                setState(() {});
              },
              duration: Duration(seconds: 1),
              child: FlutterLogo(
                size: 60,
              ),
            ),
          ),
        ),
      ],
    );
animated_container_13.gif
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,163评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,301评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,089评论 0 352
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,093评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,110评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,079评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,005评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,840评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,278评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,497评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,394评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,980评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,628评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,649评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,548评论 2 352

推荐阅读更多精彩内容