Flutter(二十六)——自定義路由

PageRouteBuilder

前面我們介紹的所有路由都是MaterialPageRoute。但這並不能滿足項目中的實際需求,有時候我們也需要修改路由默認的轉場效果,這個時候就需要自定義路由,要用到另一個類,它就是PageRouteBuilder,首先我們來看看它的源碼:

PageRouteBuilder({
    RouteSettings settings,
    @required this.pageBuilder,
    this.transitionsBuilder = _defaultTransitionsBuilder,
    this.transitionDuration = const Duration(milliseconds: 300),
    this.opaque = true,
    this.barrierDismissible = false,
    this.barrierColor,
    this.barrierLabel,
    this.maintainState = true,
    bool fullscreenDialog = false,
  }) : assert(pageBuilder != null),
       assert(transitionsBuilder != null),
       assert(opaque != null),
       assert(barrierDismissible != null),
       assert(maintainState != null),
       assert(fullscreenDialog != null),
       super(settings: settings, fullscreenDialog: fullscreenDialog);

屬性講解

我們來看一下PageRouteBuilder源碼中幾個重要的屬性,如下圖所示:

屬性 取值
Opaque 是否遮擋整個屏幕
transitionsBuilder 用於自定義的轉場效果
pageBuilder 用來創建所要跳轉到的頁面
transitionDuration 轉場動畫的持續時間

自定義路由轉場效果

介紹完幾個重要的屬性,我們就直接來實戰把,這裏我們將通過一個自定義的Widget和PageRouteBuild,實現一個簡單的Hero效果的路由轉場,首先,我們定義一個方法,用於路由的切換,代碼如下:

_customToButton(Widget page){
    Navigator.of(context).push(
      PageRouteBuilder<Null>(
        pageBuilder: (BuildContext context,Animation<double> anim1,Animation<double> anim2){
          return AnimatedBuilder(
            animation: anim1,
            builder: (BuildContext context,Widget child){
              return Opacity(
                opacity: anim1.value,
                child: page,
              );
            },
          );
        },
        transitionDuration: Duration(milliseconds: 600)
      ),
    );
  }

屬性上面對應的表格都有,其他屬性一眼就能看出來,這裏就不在贅述,接着我們需要定義一個通過Hero動畫變化的一個CustomLogo自定義圖標,代碼如下:

class CustomLogo extends StatelessWidget{
  final double size;

  CustomLogo({this.size=200.0});

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.blueAccent,
      width: size,
      height: size,
      child: Center(
        child: FlutterLogo(
          size: size,
        ),
      ),
    );
  }

}

然後,我們需要完善主界面的元素,需要Button點擊實現路由的跳轉,代碼如下:

class _MyHomePageState extends State<MyHomePage> {

  _customToButton(Widget page){
    ....代碼在上面
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          children: <Widget>[
            RaisedButton(
              padding: EdgeInsets.all(10),
              onPressed: (){
                _customToButton(Page2());
              },
              child: Text(
                '跳轉自定義路由',
                textAlign: TextAlign.center,
                style: TextStyle(fontSize: 15),
              ),
            ),
            Hero(
              tag: 'hero1',
              child: ClipOval(
                child: CustomLogo(size: 60,),
              ),
            ),
            Hero(
              tag: 'hero2',
              child: Material(
                color: Colors.transparent,
                child: Text(
                  '動畫',
                  style: TextStyle(fontSize: 15,color: Colors.red),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

前面我們講過,如果需要實現Hero動畫,必須定義源和目標,所以我們跳轉的界面也要有一個tag是hero1,代碼如下:

class Page2 extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Padding(
        padding: EdgeInsets.all(30.0),
        child: Stack(
          children: <Widget>[
            Align(
              alignment: Alignment.center,
              child: Hero(
                tag: "hero1",
                child: Container(
                  height: 250.0,
                  width: 250.0,
                  child: CustomLogo(),
                ),
              ),
            ),
            OutlineButton(
              onPressed: () => Navigator.of(context).pop(),
              child: Icon(Icons.close),
            )
          ],
        ),
      ),
    );
  }
}

上面的代碼都是前面講解過的基本元素,除了第一段代碼提取出來的方法_customToButton,其他的都使用過,不懂的可以前往前面的章節瞭解。最後我們運行一下,就實現如下效果:
實現效果

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章