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,其他的都使用过,不懂的可以前往前面的章节了解。最后我们运行一下,就实现如下效果:
实现效果

发布了117 篇原创文章 · 获赞 147 · 访问量 122万+

猜你喜欢

转载自blog.csdn.net/liyuanjinglyj/article/details/105032026