Flutter - 內建動畫 API

前行的烏龜發表於2019-12-20

Flutter - 內建動畫 API

Flutter 內建動畫

上面的那些一般用起來不是很方便,即便是 AnimatedBuilder 還是要指定參與動畫變化的 widget 屬性,為了進一步方便我們,官方在 AnimatedWidget 的基礎上封裝了下面這些內建動畫庫,就是 android 中的那些,當然更多一些:

  • SlideTransition - 自身倍數位移動畫
  • AlignTransition - 沒找到資料
  • PositionedTransition - 縮放動畫,限定父佈局只能是 stack
  • FadeTransition - 透明度動畫
  • ScaleTransition - 縮放動畫,這個是 android 中的那種縮放動畫,可以指定中心點
  • SizeTransition - 寬高動畫,限制是每次只能執行一個維度的動畫,寬和高一起不行,那就是縮放動畫了
  • RotationTransition - 旋轉動畫,特點是其數值是 0-1 之間的,旋轉90度 = 0.25

這些 transition 的特點就是,用一個引數接受 animation 動畫,child 寫 widget


FadeTransition

FadeTransition 是透明度動畫,引數就是一個 opacity 指定動畫,child 寫 widget 就沒了

animationController = AnimationController(
  duration: Duration(milliseconds: 300),
  vsync: this,
);

animation = CurvedAnimation(parent: animationController, curve: Curves.bounceInOut);
animation = Tween(begin: 0.0, end: 1.0).animate(animationController);
複製程式碼
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          FadeTransition(
            opacity: animation,
            child: Container(
              margin: EdgeInsets.only(bottom: 20),
              width: 300,
              height: 300,
              color: Colors.blueAccent,
            ),
          ),
          RaisedButton(
            child: Text("放大"),
            onPressed: () {
              animationController?.forward();
            },
          ),
        ],
      ),
    );
  }
}
複製程式碼

SlideTransition

SlideTransition 位移動畫,使用 offset 來承載x,y軸資料。需要注意的是 Offset(0.0, 0.0) 中的數值都是 倍數,也就是說 SlideTransition 只支援按 widget 本身長寬的倍數位移,不支援具體的數值的位移操作

  void initState() {
    super.initState();

    animationController = AnimationController(
      duration: Duration(milliseconds: 300),
      vsync: this,
    );

    animation = Tween(begin: Offset(0.0, 0.0), end: Offset(1.0, 1.0))
        .animate(animationController);
  }
複製程式碼
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          SlideTransition(
            position: animation,
            child: Container(
              margin: EdgeInsets.only(bottom: 20),
              width: 100,
              height: 100,
              color: Colors.blueAccent,
            ),
          ),
          RaisedButton(
            child: Text("放大"),
            onPressed: () {
              animationController?.forward();
            },
          ),
        ],
      ),
    );
  }
複製程式碼

PositionedTransition

PositionedTransition 縮放動畫,必須在 stack 中使用,其縮放數值使用 RelativeRect 包裹,前後變化的是距 stack 父佈局左上右下4個角的距離:

    animation = RelativeRectTween(
            begin: RelativeRect.fromLTRB(0, 0, 0, 0),
            end: RelativeRect.fromLTRB(50, 200, 50, 200))
        .animate(animationController);
複製程式碼

大家看個圖:

Flutter - 內建動畫 API

Flutter - 內建動畫 API

基本上就是這個思路了,限制有一些,下面是例子程式碼,不是上面 gif 的程式碼:

  Animation<RelativeRect> animation;
  AnimationController animationController;
  CurvedAnimation curve;

  void initState() {
    super.initState();

    animationController = AnimationController(
      duration: Duration(milliseconds: 300),
      vsync: this,
    );

    curve = CurvedAnimation(parent: animationController, curve: Curves.bounceInOut);
    
    animation = RelativeRectTween(
            begin: RelativeRect.fromLTRB(0, 0, 0, 0),
            end: RelativeRect.fromLTRB(50, 200, 50, 200))
        .animate(curve);
  }
複製程式碼
  Widget build(BuildContext context) {
    return Center(
      child: Stack(
        children: <Widget>[
          PositionedTransition(
            rect: animation,
            child: Container(
              width: 300,
              height: 300,
              color: Colors.blueAccent,
            ),
          ),
          Positioned(
            top: 20,
            left: 20,
            child: RaisedButton(
              child: Text("放大"),
              onPressed: () {
                animationController?.forward();
              },
            ),
          ),
        ],
      ),
    );
  }
複製程式碼

最後大家注意啊,RelativeRectTween begin 的數值能影響 widget 初始顯示時的寬高大小


ScaleTransition

ScaleTransition 這才是傳統的縮放動畫,使用 alignment: Alignment.topLeft 指定縮放中心點

  Animation<double> animation;
  AnimationController animationController;
  CurvedAnimation curve;

  @override
  void initState() {
    super.initState();

    animationController = AnimationController(
      duration: Duration(milliseconds: 300),
      vsync: this,
    );

    curve =
        CurvedAnimation(parent: animationController, curve: Curves.bounceInOut);
    animation = Tween(
      begin: 1.0,
      end: 0.3,
    ).animate(curve);
  }

複製程式碼
  Widget build(BuildContext context) {
    return Center(
      child: Stack(
        children: <Widget>[
          ScaleTransition(
            alignment: Alignment.topLeft,
            scale: animation,
            child: Container(
              width: 300,
              height: 300,
              color: Colors.blueAccent,
            ),
          ),
          Positioned(
            top: 20,
            left: 20,
            child: RaisedButton(
              child: Text("放大"),
              onPressed: () {
                animationController?.forward();
              },
            ),
          ),
        ],
      ),
    );
  }
複製程式碼

SizeTransition

SizeTransition 寬高動畫,限制是每次只能設定一個維度,不能寬和高一起,優點是寬高的變化不會引起內容的變形

axis: Axis.horizontal 就是指定動畫作用與寬還是高

Flutter - 內建動畫 API

  Widget build(BuildContext context) {
    return Center(
      child: Stack(
        children: <Widget>[
          SizeTransition(
            axis: Axis.horizontal,
            sizeFactor: animation,
            child: Container(
              color: Colors.blueAccent,
              child: Icon(Icons.access_alarm, size: 300),
            ),
          ),
          Positioned(
            top: 20,
            left: 20,
            child: RaisedButton(
              child: Text("放大"),
              onPressed: () {
                animationController?.forward();
              },
            ),
          ),
        ],
      ),
    );
  }
複製程式碼

RotationTransition

RotationTransition 旋轉動畫,特點是其數值是 0-1 之間的,旋轉90度 = 0.25,依然可以設定原點

animation = Tween(
  begin: 0.0,
  end: 0.25,
).animate(curve);
複製程式碼
  Widget build(BuildContext context) {
    return Center(
      child: Stack(
        children: <Widget>[
          RotationTransition(
            turns: animation,
            alignment: Alignment.center,
            child: Container(
              color: Colors.blueAccent,
              child: Icon(Icons.access_alarm, size: 300),
            ),
          ),
          Positioned(
            top: 20,
            left: 20,
            child: RaisedButton(
              child: Text("放大"),
              onPressed: () {
                animationController?.forward();
              },
            ),
          ),
        ],
      ),
    );
  }
複製程式碼

相關文章