[- Flutter福利篇 -] Hero轉場組件共享 — 附贈-路由動畫工具類

最近比較忙,不多發文章了。今天抽空把Hero的轉場組件共享說一下
順便發個轉場的動畫福利類,能夠定義轉場的時間,曲線,別客氣,隨便拿去用。
廢話很少說,先看圖:bash


  • 1.透明:FadeRouter


  • 2.縮放:ScaleRouter


  • 3.旋轉:RotateRouter


  • 4.透明+縮放+旋轉

  • 5.右--->左:Right2LeftRouter


  • 6.左--->右:Left2RightRouter


  • 7.上--->下:Top2BottomRouter


  • 8.下--->上:Bottom2TopRouter


Hero元素共享

也許上面吸引你的不是界面跳轉的動畫,而是那個頭像神奇般的軌跡。下面就來講一下如何實現。微信

起始頁:OriginPage
class OriginPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
      var hero= Hero(//----定義一個Hero,並添加tag標籤,此中組件共享
        tag: 'user-head',
        child: ClipRRect(
          borderRadius: BorderRadius.all(Radius.circular(30)),
          child: Image.asset(
            "images/mani.jpg",width: 60,height: 60,fit: BoxFit.cover,
          ),
        ),
      );

      var container= Container(//容器,沒啥好說的
        alignment: Alignment(-0.8, -0.8),
        child: hero,
        width: 250,
        height: 250*0.618,
        decoration: BoxDecoration(//添加漸變色
        gradient: LinearGradient(colors: [Colors.red.withAlpha(99),Colors.yellow.withAlpha(189),Colors.green.withAlpha(88),Colors.blue.withAlpha(230)])
      ),);

    return Scaffold(
      body: Center(//點擊跳轉
        child: GestureDetector(child: Card(elevation:5,child:container ,),onTap: (){
          _toNext(context);
        },),
      ),
    );
  }

  void _toNext(context) {//跳轉路由
    Navigator.push(
        context,
//      FadeRouter(child:TargetPage()),
//      ScaleRouter(child:TargetPage()),
//      RotateRouter(child:TargetPage()),
//      ScaleFadeRotateRouter(child:TargetPage()),
//      Right2LeftRouter(child:TargetPage()),
//      Left2RightRouter(child:TargetPage()),
//      Top2BottomRouter(child:TargetPage()),
      Bottom2TopRouter(child:TargetPage()),//跳轉+動畫
    );
  }
}
複製代碼
目標頁:TargetPage
class TargetPage extends StatelessWidget {
  
  @override
  Widget build(BuildContext context) {
    var hero=Hero(//----定義一個Hero,爲其添加標籤,兩個標籤相同,則能夠共享
      tag: 'user-head',
      child: Padding(
        padding: EdgeInsets.all(16.0),
        child: CircleAvatar(
          backgroundColor: Colors.transparent,
          radius: 72.0,
          backgroundImage: AssetImage(
            "images/mani.jpg",
          ),
        ),
      ),
    );

    var touch=InkWell(onTap: (){
      Navigator.of(context).pop();
    },child: hero,);

    return Scaffold(
      appBar: AppBar(leading:touch ,),
      body: Container(
        decoration: BoxDecoration(
            gradient: LinearGradient(colors: [Colors.red.withAlpha(99),Colors.yellow.withAlpha(189),Colors.green.withAlpha(88),Colors.blue.withAlpha(230)])
        ),
      ),
    );
  }
}
複製代碼

關於createRectTween屬性

在回調中會給兩個初始和結束的兩個矩形,能夠進行矩形動畫來控制共享組件的區域,以下圖在目標頁:app

var height=MediaQuery.of(context).size.height;
var width=MediaQuery.of(context).size.width;
var size=min(height,width);

 var hero=Hero(//----定義一個Hero,爲其添加標籤,兩個標籤相同,則能夠共享
      createRectTween: ((r1,r2){
        return RectTween(begin: Rect.fromLTWH(size/2,0, size, size),end:  r2);
      }),
複製代碼

另外還有個要點:同一頁面不能出現多處同名Heroless


福利時間:路由動畫工具

使用方法看上面的路由跳轉處,固然你也能夠根據下面的定製更酷炫的跳轉效果。ide

import 'package:flutter/cupertino.dart';

//縮放路由動畫
class ScaleRouter<T> extends PageRouteBuilder<T> {
  final Widget child;
  final int duration_ms;
  final Curve curve;
  ScaleRouter({this.child, this.duration_ms = 500,this.curve=Curves.fastOutSlowIn})
      : super(
    pageBuilder: (context, animation, secondaryAnimation) => child,
    transitionDuration: Duration(milliseconds: duration_ms),
    transitionsBuilder: (context, a1, a2, child) =>
        ScaleTransition(
          scale: Tween(begin: 0.0, end: 1.0).animate(
              CurvedAnimation(parent: a1, curve: curve)),
          child: child,
        ),
  );
}
//漸變透明路由動畫
class FadeRouter<T> extends PageRouteBuilder<T> {
  final Widget child;
  final int duration_ms;
  final Curve curve;
  FadeRouter({this.child, this.duration_ms = 500,this.curve=Curves.fastOutSlowIn})
      : super(
      pageBuilder: (context, animation, secondaryAnimation) => child,
      transitionDuration: Duration(milliseconds: duration_ms),
      transitionsBuilder: (context, a1, a2, child) =>
          FadeTransition(
            opacity: Tween(begin: 0.1, end: 1.0).animate(
                CurvedAnimation(parent: a1, curve:curve,)),
            child: child,
          ));
}

//旋轉路由動畫
class RotateRouter<T> extends PageRouteBuilder<T> {
  final Widget child;
  final int duration_ms;
  final Curve curve;
  RotateRouter({this.child, this.duration_ms = 500,this.curve=Curves.fastOutSlowIn})
      : super(
      pageBuilder: (context, animation, secondaryAnimation) => child,
      transitionDuration: Duration(milliseconds: duration_ms),
      transitionsBuilder: (context, a1, a2, child) =>
          RotationTransition(
            turns: Tween(begin: 0.1, end: 1.0).animate(
                CurvedAnimation(parent: a1, curve:curve,)),
            child: child,
          ));
}

//右--->左
class Right2LeftRouter<T> extends PageRouteBuilder<T> {
  final Widget child;
  final int duration_ms;
  final Curve curve;
  Right2LeftRouter({this.child,this.duration_ms=500,this.curve=Curves.fastOutSlowIn})
      :super(
      transitionDuration:Duration(milliseconds: duration_ms),
      pageBuilder:(ctx,a1,a2){return child;},
      transitionsBuilder:(ctx,a1,a2,Widget child,) {
        return SlideTransition(
            position: Tween<Offset>(
              begin: Offset(1.0, 0.0), end: Offset(0.0, 0.0),).animate(
                CurvedAnimation(parent: a1, curve: curve)),
            child:  child
        );
      });
}

//左--->右
class Left2RightRouter<T> extends PageRouteBuilder<T> {
  final Widget child;
  final int duration_ms;
  final Curve curve;
  List<int> mapper;
  Left2RightRouter({this.child,this.duration_ms=500,this.curve=Curves.fastOutSlowIn})
      :assert(true),super(
      transitionDuration:Duration(milliseconds: duration_ms),
      pageBuilder:(ctx,a1,a2){return child;},
      transitionsBuilder:(ctx,a1,a2,Widget child,) {
        return SlideTransition(
            position: Tween<Offset>(
              begin: Offset(-1.0, 0.0), end: Offset(0.0, 0.0),).animate(
                CurvedAnimation(parent: a1, curve: curve)),
            child:  child
        );
      });
}

//上--->下
class Top2BottomRouter<T> extends PageRouteBuilder<T> {
  final Widget child;
  final int duration_ms;
  final Curve curve;
  Top2BottomRouter({this.child,this.duration_ms=500,this.curve=Curves.fastOutSlowIn})
      :super(
      transitionDuration:Duration(milliseconds: duration_ms),
      pageBuilder:(ctx,a1,a2){return child;},
      transitionsBuilder:(ctx,a1,a2,Widget child,) {
        return SlideTransition(
            position: Tween<Offset>(
              begin: Offset(0.0,-1.0), end: Offset(0.0, 0.0),).animate(
                CurvedAnimation(parent: a1, curve: curve)),
            child:  child
        );
      });
}

//下--->上
class Bottom2TopRouter<T> extends PageRouteBuilder<T> {
  final Widget child;
  final int duration_ms;
  final Curve curve;
  Bottom2TopRouter({this.child,this.duration_ms=500,this.curve=Curves.fastOutSlowIn})
      :super(
      transitionDuration:Duration(milliseconds: duration_ms),
      pageBuilder:(ctx,a1,a2){return child;},
      transitionsBuilder:(ctx,a1,a2,Widget child,) {
        return SlideTransition(
            position: Tween<Offset>(
              begin: Offset(0.0, 1.0), end: Offset(0.0, 0.0),).animate(
                CurvedAnimation(parent: a1, curve: curve)),
            child:  child
        );
      });
}

//縮放+透明+旋轉路由動畫
class ScaleFadeRotateRouter<T> extends PageRouteBuilder<T> {
  final Widget child;
  final int duration_ms;
  final Curve curve;
  ScaleFadeRotateRouter({this.child, this.duration_ms = 500,this.curve=Curves.fastOutSlowIn}) : super(
      transitionDuration: Duration(milliseconds: duration_ms),
      pageBuilder: (ctx, a1, a2)=>child,//頁面
      transitionsBuilder: (ctx, a1, a2, Widget child,) {//構建動畫
        return RotationTransition(//旋轉動畫
          turns: Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation(
            parent: a1,
            curve: curve,
          )),
          child: ScaleTransition(//縮放動畫
            scale: Tween(begin: 0.0, end: 1.0).animate(
                CurvedAnimation(parent: a1, curve: curve)),
            child: FadeTransition(opacity://透明度動畫
            Tween(begin: 0.5, end: 1.0).animate(CurvedAnimation(parent: a1, curve: curve)),
              child: child,),
          ),
        );
      });
}
//無動畫
class NoAnimRouter<T> extends PageRouteBuilder<T> {
  final Widget page;
  NoAnimRouter(this.page)
      : super(
      opaque: false,
      pageBuilder: (context, animation, secondaryAnimation) => page,
      transitionDuration: Duration(milliseconds: 0),
      transitionsBuilder:
          (context, animation, secondaryAnimation, child) => child);
}

複製代碼
結語

本文到此接近尾聲了,若是想快速嚐鮮Flutter,《Flutter七日》會是你的必備佳品;若是想細細探究它,那就跟隨個人腳步,完成一次Flutter之旅。
另外本人有一個Flutter微信交流羣,歡迎小夥伴加入,共同探討Flutter的問題,本人微信號:zdl1994328,期待與你的交流與切磋。工具

相關文章
相關標籤/搜索