Flutter開發日記——Flutter動畫&Motion Widget詳解(下)

YYDev發表於2019-11-07

本篇文章已授權微信公眾號 YYGeeker 獨家釋出轉載請標明出處

AnimatedDefaultTextStyle

1、簡介

  • AnimatedDefaultTextStyle控制元件表示一個具有變化文字樣式的動畫控制元件
  • AnimatedDefaultTextStyle通過修改元件的style屬性,系統將會通過動畫的方式自動切換到新的style樣式

2、建構函式

AnimatedDefaultTextStyle({
    Key key,
    @required this.child,
    @required this.style,
    this.textAlign,
    this.softWrap = true,
    this.overflow = TextOverflow.clip,
    this.maxLines,
    Curve curve = Curves.linear,
    @required Duration duration,
    Duration reverseDuration,
})
複製程式碼
  • child:子控制元件,通常用Text元件
  • style:子控制元件的樣式,用於動畫變化
  • textAlign:如果文字超過1行時,所有換行的字型的對齊方式,可以是左對齊、右對齊
  • softWrap:文字是否應該在軟換行符處換行,軟換行和硬換行是word用法,具體自閱
  • overflow:超過文字行數區域的裁剪方式
  • maxLines:文字最大行數,預設是1
  • curve:動畫插值器
  • duration:動畫播放時長
  • reverseDuration:倒退動畫播放時長

3、例子

通過_isSelected的值控制樣式的切換

AnimatedDefaultTextStyle(
  softWrap: false,
  textAlign: TextAlign.right,
  maxLines: 2,
  overflow: TextOverflow.ellipsis,
  curve: Curves.linear,
  duration: Duration(seconds: 1),
  child: Text("Flutter message you!!!"),
  style: _isSelected
      ? TextStyle(
          fontSize: 10.0,
          color: Colors.red,
          fontWeight: FontWeight.bold,
        )
      : TextStyle(
          fontSize: 50.0,
          color: Colors.black,
          fontWeight: FontWeight.w300,
        ),
),
複製程式碼

通過計時器控制樣式的切換

Timer.periodic(Duration(seconds: 1), (timer) {
  setState(() {
    switch (time % 4) {
      case 0:
        _isSelected = false;
        break;
      case 2:
        _isSelected = true;
        break;
    }
    time++;
  });
});
複製程式碼

在這裡插入圖片描述

AnimatedListState/AnimatedList

1、簡介

  • AnimatedListState控制元件表示一個具有動畫的列表控制元件
  • AnimatedListState控制元件作為AnimatedList控制元件的key進行使用,可以控制列表動畫和增刪操作

2、建構函式

const AnimatedList({
    Key key,
    @required this.itemBuilder,
    this.initialItemCount = 0,
    this.scrollDirection = Axis.vertical,
    this.reverse = false,
    this.controller,
    this.primary,
    this.physics,
    this.shrinkWrap = false,
    this.padding,
})
複製程式碼
  • itemBuilder:列表條目的構建者
  • initialItemCount:列表初始化條目的個數
  • scrollDirection:滾動的方向
  • reverse:是否翻轉
  • controller:滾動控制器
  • primary:是否當使用者點選狀態列時,該檢視會滾動到頂部,只適用於iOS,預設支援
  • physics:控制使用者滾動檢視的互動
    • AlwaysScrollableScrollPhysics:列表總是可滾動的
    • PageScrollPhysics:一頁一頁的列表滑動,一般用於PageView控制元件用的滑動效果,滑動到末尾會有比較大的彈起
    • ClampingScrollPhysics:滾動時沒有回彈效果
    • NeverScrollableScrollPhysics:就算內容超過列表範圍也不會滑動
    • BouncingScrollPhysics:不論什麼平臺都會有回彈效果
    • FixedExtentScrollPhysics:僅滾動到子項而不存在任何偏移,必須與使用FixedExtentScrollController的可滾動物件一起使用
  • shrinkWrap:是否根據子widget的總長度來設定ListView的長度
  • padding:父控制元件的內邊距

3、例子

通過點選加號隨機生成字串,對列表進行增加操作,通過點選條目的刪除圖示,對列表進行刪除操作

class WeWidgetState extends State<WeWidget> {
  var data = <String>[];
  var tween = Tween<Offset>(begin: Offset(1, 0), end: Offset(0, 0));
  final animatedKey = GlobalKey<AnimatedListState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('day19'),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          var str = Random().nextInt(1000).toString();
          data.add(str);
          var index = data.lastIndexOf(str);
          animatedKey.currentState.insertItem(index);
        },
        child: Icon(Icons.add),
      ),
      body: AnimatedList(
        physics: BouncingScrollPhysics(),
        padding: EdgeInsets.all(12.0),
        scrollDirection: Axis.vertical,
        primary: true,
        reverse: false,
        shrinkWrap: false,
        key: animatedKey,
        initialItemCount: data.length,
        itemBuilder: (context, int index, Animation<double> animation) {
          return animationListItem(data[index], animation);
        },
      ),
    );
  }

  Widget animationListItem(String str, animation) {
    return SlideTransition(
      position: animation.drive(tween),
      child: listItem(str),
    );
  }

  Widget listItem(String str) {
    return ListTile(
      title: Text('$str', style: TextStyle(fontSize: 30)),
      trailing: IconButton(
        icon: Icon(Icons.delete_forever),
        onPressed: () {
          var index = data.indexOf(str);
          data.remove(str);
          animatedKey.currentState.removeItem(
              index, (context, animation) => animationListItem(str, animation));
        },
      ),
    );
  }
}
複製程式碼

在這裡插入圖片描述

AnimatedModalBarrier

1、簡介

  • AnimatedModalBarrier控制元件表示一個具有顏色值變化的動畫控制元件
  • AnimatedModalBarrier控制元件可防止使用者與其自身背後的小部件進行互動,並且可以使用顏色動畫進行過渡
  • AnimatedModalBarrier控制元件舉例說明,當螢幕上出現對話方塊時,對話方塊下方的頁面通常會被ModalBarrier變暗

2、建構函式

const AnimatedModalBarrier({
    Key key,
    Animation<Color> color,
    this.dismissible = true,
    this.semanticsLabel,
    this.barrierSemanticsDismissible,
})
複製程式碼
  • color:顏色值動畫變化
  • dismissible:是否觸控當前ModalBarrier將彈出當前路由,配合點選事件彈出路由使用
  • semanticsLabel:語義化標籤
  • barrierSemanticsDismissible:語義樹中是否包括ModalBarrier語義

3、例子

Widget _buildColumn() {
    return Center(
      child: Container(
        width: 200,
        height: 200,
        child: AnimatedModalBarrier(
          semanticsLabel: "StackBarrier",
          barrierSemanticsDismissible: true,
          dismissible: true,
          color: _animation,
        ),
      ),
    );
}
複製程式碼

在這裡插入圖片描述

AnimatedOpacity

1、簡介

  • AnimatedOpacity控制元件表示一個具有透明度變化的動畫控制元件

2、建構函式

const AnimatedOpacity({
    Key key,
    this.child,
    @required this.opacity,
    Curve curve = Curves.linear,
    @required Duration duration,
})
複製程式碼
  • child:子控制元件
  • opacity:透明度動畫變化值
  • curve:動畫的插值器
  • duration:動畫的時長

3、例子

通過定時器改變透明度的大小

class WeWidgetState extends State<WeWidget> {
  WeWidgetState() {
    Timer.periodic(Duration(milliseconds: 1000), (timer) {
      setState(() {
        switch (time % 2) {
          case 0:
            _opacity = 0.3;
            break;
          case 1:
            _opacity = 1.0;
            break;
        }
        time++;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("day21"),
      ),
      body: _buildColumn(),
    );
  }

  Widget _buildColumn() {
    return Center(
      child: AnimatedOpacity(
        curve: Curves.fastOutSlowIn,
        opacity: _opacity,
        duration: Duration(seconds: 1),
        child: FlutterLogo(
          style: FlutterLogoStyle.horizontal,
          size: 200,
        ),
      ),
    );
  }
}
複製程式碼

在這裡插入圖片描述

AnimatedPhysicalModel

1、簡介

  • AnimatedPhysicalModel控制元件表示一個具有陰影背景動畫的控制元件

2、建構函式

const AnimatedPhysicalModel({
    Key key,
    @required this.child,
    @required this.shape,
    this.clipBehavior = Clip.none,
    this.borderRadius = BorderRadius.zero,
    @required this.elevation,
    @required this.color,
    this.animateColor = true,
    @required this.shadowColor,
    this.animateShadowColor = true,
    Curve curve = Curves.linear,
    @required Duration duration,
})
複製程式碼
  • child:子控制元件
  • shape:陰影的形狀
  • clipBehavior:陰影的裁剪方式
    • Clip.none:無模式
    • Clip.hardEdge:裁剪速度稍快,但容易失真,有鋸齒
    • Clip.antiAlias:裁剪邊緣抗鋸齒,使得裁剪更平滑,這種模式裁剪速度比antiAliasWithSaveLayer快,但是比hardEdge慢
    • Clip.antiAliasWithSaveLayer:裁剪後具有抗鋸齒特性並分配螢幕緩衝區,所有後續操作在緩衝區進行
  • borderRadius:背景的邊框
  • elevation:陰影顏色值的深度
  • color:背景色
  • animateColor:背景色是否用動畫形式展示
  • shadowColor:陰影的動畫值
  • animateShadowColor:陰影是否用動畫形式展示
  • curve:動畫的插值器
  • duration:動畫的時長

3、例子

Widget _buildColumn() {
    return Center(
      child: AnimatedPhysicalModel(
        curve: Curves.fastOutSlowIn,
        color: Colors.grey.withOpacity(0.2),
        clipBehavior: Clip.antiAliasWithSaveLayer,
        borderRadius: BorderRadius.circular(12.0),
        animateColor: true,
        animateShadowColor: true,
        shape: BoxShape.rectangle,
        shadowColor: _shadowColor,
        elevation: 20.0,
        duration: Duration(seconds: 1),
        child: FlutterLogo(
          style: FlutterLogoStyle.horizontal,
          size: 200,
        ),
      ),
    );
  }
複製程式碼

在這裡插入圖片描述

AnimatedPositioned

1、簡介

  • AnimatedPositioned控制元件表示一個具有位置變化動畫的控制元件

2、建構函式

const AnimatedPositioned({
    Key key,
    @required this.child,
    this.left,
    this.top,
    this.right,
    this.bottom,
    this.width,
    this.height,
    Curve curve = Curves.linear,
    @required Duration duration,
})
複製程式碼
  • child:子控制元件
  • left:左邊距離
  • top:上邊距離
  • right:右邊距離
  • bottom:下邊距離
  • width:控制元件的寬度
  • height:控制元件的高度
  • curve:動畫的插值器
  • duration:動畫的時長

3、例子

通過改變左上角位置和寬高進行動畫播放

class WeWidgetState extends State<WeWidget> {
  WeWidgetState() {
    Timer.periodic(Duration(milliseconds: 1000), (timer) {
      setState(() {
        switch (time % 2) {
          case 0:
            _width = 100.0;
            break;
          case 1:
            _width = 200.0;
            break;
        }
        time++;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("day23"),
      ),
      body: _buildColumn(),
    );
  }

  Widget _buildColumn() {
    return Stack(
      children: <Widget>[
        AnimatedPositioned(
          curve: Curves.fastOutSlowIn,
          width: _width,
          height: _width,
          top: _width,
          left: _width,
          duration: Duration(seconds: 1),
          child: FlutterLogo(
            style: FlutterLogoStyle.horizontal,
            size: 200,
          ),
        ),
      ],
    );
  }
}
複製程式碼

在這裡插入圖片描述

AnimatedSize

1、簡介

  • AnimatedSize控制元件表示一個具有尺寸變化動畫的控制元件

2、建構函式

const AnimatedSize({
    Key key,
    Widget child,
    this.alignment = Alignment.center,
    this.curve = Curves.linear,
    @required this.duration,
    this.reverseDuration,
    @required this.vsync,
})
複製程式碼
  • child:子控制元件
  • alignment:子控制元件的對齊方式
  • curve:動畫的插值器
  • duration:動畫的時長
  • reverseDuration:翻轉動畫的時長
  • vsync:是否開啟垂直同步

3、例子

class WeWidgetState extends State<WeWidget>
    with SingleTickerProviderStateMixin {
  WeWidgetState() {
    Timer.periodic(Duration(milliseconds: 1000), (timer) {
      setState(() {
        switch (time % 2) {
          case 0:
            _width = 100.0;
            break;
          case 1:
            _width = 200.0;
            break;
        }
        time++;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("day24"),
      ),
      body: _buildColumn(),
    );
  }

  Widget _buildColumn() {
    return Center(
      child: AnimatedSize(
        alignment: Alignment.center,
        curve: Curves.fastOutSlowIn,
        vsync: this,
        duration: Duration(seconds: 1),
        reverseDuration: Duration(seconds: 2),
        child: FlutterLogo(
          style: FlutterLogoStyle.horizontal,
          size: _width,
        ),
      ),
    );
  }
}
複製程式碼

在這裡插入圖片描述

作者

Flutter開發日記——Flutter動畫&Motion Widget詳解(下)
Hensen_

相關文章