英雄动画在嵌套导航器中不起作用

Mik*_*ail 5 dart flutter flutter-animation

我试图在我的第一个flutter应用程序中使用Hero Animations,但已经有使用这种方法实现的instagram,如底部导航,并且我发现Hero Animations在嵌套的Navigators中不起作用。

例如,您可以从此处获取Complete示例,然后从class 替换为home: MainScreen(),HeroApp

home: Navigator(onGenerateRoute: (_) {
  return MaterialPageRoute(builder: (_) => MainScreen());
}),
Run Code Online (Sandbox Code Playgroud)

和英雄动画将中断。

也许还有其他方法可以实现每个选项卡具有独立堆栈的底部导航,这些方法不使用嵌套导航器,但是我没有找到任何方法。

因此,任何建议非常感谢。

UPD:我刚刚意识到答案应该在MaterialApp课堂和宾果游戏中!

有一个天真的解决方案可以工作:

home: Navigator(
  onGenerateRoute: (_) => MaterialPageRoute(builder: (_) => MainScreen()),
  observers: [HeroController()],
),
Run Code Online (Sandbox Code Playgroud)

但是在MaterialApp源代码中,事情要复杂得多,所以也许有些隐藏的事情打破了我的幼稚解决方案。因此问题仍然悬而未决。

Vot*_*gus 18

这是因为Hero依赖于一个HeroControllerMaterialApp中的导航器有但您的自定义导航器没有,要解决这个问题,只需添加控制器,就像这样。

import 'package:flutter/material.dart';

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  HeroController _heroController;

  @override
  void initState() {
    super.initState();
    _heroController = HeroController(createRectTween: _createRectTween);
  }

  @override
  Widget build(BuildContext context) {
    return Navigator(
      observers: [_heroController],
      onGenerateRoute: (settings) {
        return MaterialPageRoute(
            settings: settings, builder: (context) => Text(''));
      },
    );
  }

  RectTween _createRectTween(Rect begin, Rect end) {
    return MaterialRectArcTween(begin: begin, end: end);
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 考虑重构它以使用 [`HeroControllerScope`](https://flutter.dev/docs/release/writing-changes/hero-controller-scope) 小部件。 (5认同)

Eri*_* Su 5

2022 年 8 月更新:

对于已接受的答案,更好的解决方案是将每个 Navigator 小部件包装在 HeroControllerScope 小部件中,如图所示。

import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      builder: (BuildContext context, Widget child) {
        // Builds two parallel navigators.
        return Stack(
          children: <Widget>[
            HeroControllerScope(
              controller: MaterialApp.createMaterialHeroController(),
              child: Navigator(
                onGenerateRoute: (RouteSettings settings) {
                  return MaterialPageRoute<void>(
                    settings: settings,
                    builder: (BuildContext context) {
                      return const Text('first Navigator');
                    }
                  );
                },
              ),
            ),
            HeroControllerScope(
              controller: MaterialApp.createMaterialHeroController(),
              child: Navigator(
                onGenerateRoute: (RouteSettings settings) {
                  return MaterialPageRoute<void>(
                    settings: settings,
                    builder: (BuildContext context) {
                      return const Text('second Navigator');
                    }
                  );
                },
              ),
            ),
          ],
        );
      }
    )
  );
}
Run Code Online (Sandbox Code Playgroud)