带AlertDialog的英雄动画

Alb*_*bal 4 dart flutter

我想在主屏幕上为图像实现英雄动画,同时在对话框的内容中呈现与对话框相同图像的AlertDialog小部件。

我希望演示文稿显示在下面的屏幕截图中。当我点击左下角的图像时,我想使用英雄动画和图像的嵌入式预览以及可以点击以关闭的透明覆盖层。

在此处输入图片说明

以下代码无法执行英雄动画。

class AlertDialogTest extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Material(
      child: new InkWell(
        child: new Hero(
          tag: "preview",
          child: new Container(
            alignment: FractionalOffset.bottomLeft,
            child: new Image(
              image: new AssetImage('assets/images/theater.png'),
            ),
          ),
        ),
        onTap: () {
          showDialog(
            context: context,
            child: new AlertDialog(
              content: new Hero(
                tag: "preview",
                child: new Image(
                  image: new AssetImage('assets/images/theater.png'),
                ),
              ),
            ),
          );
        },
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

NIR*_*TEL 11

你可以你 PageRouteBuilder。

用下面的代码替换你的 onTap() 代码

Navigator.of(context).push(
    new PageRouteBuilder(
        opaque: false,
        barrierDismissible:true,
        pageBuilder: (BuildContext context, _, __) {
            return Container(
                new Hero(
                    tag: "preview",
                    child: new Image(
                        image: new AssetImage('assets/images/theater.png'),
                    ),
                ),
            );
        }
    )
)
Run Code Online (Sandbox Code Playgroud)

在此处演示示例代码。

  • 这是一个简单的解决方案 (2认同)
  • @ShubhamNarkhede Heros 可能会在转换之前、期间和之后构建多次,因此请注意您的 api 调用不在您的构建方法中 (2认同)

Col*_*son 10

英雄转换仅在的两个实例之间转换时启用PageRoute。因此,如果您想使用现有Hero系统,则可能应该使用PageRoute

AlertDialog您可以尝试使用全屏对话框,而不用按下,即可以:

Navigator.push(context, new MaterialPageRoute(
  fullscreenDialog: true,
  builder: (BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Dialog'),
      ),
      body: new Hero(
        tag: "preview",
        child: new Image(
          image: new AssetImage('assets/images/theater.png'),
        ),
      ),
    );
  }
));
Run Code Online (Sandbox Code Playgroud)

如果您需要半透明的障碍,则可以扩展PageRoute并使其更像对话框。

视频

这是一些实现上面动画的代码。

import 'package:flutter/material.dart';

void main() {
  runApp(new MaterialApp(
    home: new HomePage(),
  ));
}

class HeroDialogRoute<T> extends PageRoute<T> {
  HeroDialogRoute({ this.builder }) : super();

  final WidgetBuilder builder;

  @override
  bool get opaque => false;

  @override
  bool get barrierDismissible => true;

  @override
  Duration get transitionDuration => const Duration(milliseconds: 300);

  @override
  bool get maintainState => true;

  @override
  Color get barrierColor => Colors.black54;

  @override
  Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
    return new FadeTransition(
      opacity: new CurvedAnimation(
        parent: animation,
        curve: Curves.easeOut
      ),
      child: child
    );
  }

  @override
  Widget buildPage(BuildContext context, Animation<double> animation,
    Animation<double> secondaryAnimation) {
    return builder(context);
  }

}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Hero demo'),
      ),
      body: new Align(
        alignment: FractionalOffset.center,
        child: new Card(
          child: new Hero(
            tag: 'developer-hero',
            child: new Container(
              width: 300.0,
              height: 300.0,
              child: new FlutterLogo(),
            ),
          ),
        ),
      ),
      floatingActionButton: new FloatingActionButton(
        child: new Icon(Icons.developer_mode),
        onPressed: () {
          Navigator.push(
            context,
            new HeroDialogRoute(
              builder: (BuildContext context) {
                return new Center(
                  child: new AlertDialog(
                    title: new Text('You are my hero.'),
                    content: new Container(
                      child: new Hero(
                        tag: 'developer-hero',
                        child: new Container(
                          height: 200.0,
                          width: 200.0,
                          child: new FlutterLogo(),
                        ),
                      ),
                    ),
                    actions: <Widget>[
                      new FlatButton(
                        child: new Text('RAD!'),
                        onPressed: Navigator
                          .of(context)
                          .pop,
                      ),
                    ],
                  ),
                );
              },
            ),
          );
        },
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

根据对话框的大小和您的英雄所处的位置,Hero当第二个Hero动画完成定位后,您也许可以看到原来的内容重新出现在对话框下面。如果这让您感到困扰,则可以堆叠图像的两份副本,而最上面的一个为Hero,或者可以触发动画以隐藏原始图像Hero(也许使用AnimatedCrossFade),直到关闭对话框。

另一个选择是您可以自己实现动画,而不是使用现有Hero系统。您可能需要阅读动画文档,并可能复制了heroes.dart的片段