"No Material widget found. " 在路线之间的英雄形象动画

"No Material widget found. " at Hero image animation between routes

Flutter Newb: 我在菜单屏幕上有一个图像按钮网格。单击按钮时,它会动画化到新视图的 AppBar 的 'leading' 元素中。这正如我所期望的那样有效。 目前一切顺利...

当我 Navigator.pop() 第二个视图时,我收到错误消息“未找到 Material 小部件。”... 找不到 Material 祖先的特定小部件是:_InkResponseStateWidget... (尽管菜单屏幕确实按预期重新出现

/// ...
class MenuScreen extends StatelessWidget {
  const MenuScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Menu'),
      ),
      body: Center(
        child: GridView.count(
          crossAxisCount: 3,
          children: const [
            MenuButton('clients'),
    //...and so on

///...
class MenuButton extends StatelessWidget {
  final String indexStr;

  const MenuButton(this.indexStr, {Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Hero(
      child: InkWell(
        child: Ink.image(
          image: AssetImage('assets/images/$indexStr.png'),
          fit: BoxFit.cover,
        ),
        onTap: () => Navigator.pushNamed(context, '/' + indexStr),
        highlightColor: Colors.blue.withOpacity(0.5),
        splashColor: Colors.blue.withOpacity(0.9),
        borderRadius: BorderRadius.circular(100),
      ),
      tag: indexStr,
    );
  }
}

PS。我也不能说我完全理解所有上下文和关键内容:-)

第二个屏幕的代码是

import 'package:flutter/material.dart';

class ClientsScreen extends StatelessWidget {
  const ClientsScreen({Key? key}) : super(key: key);
  final indexStr = 'clients';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: Material(
          child: Hero(
            child: Image.asset('../assets/images/$indexStr.png'),
            tag: indexStr,
          ),
        ),
        title: const Text('Clients.'),
      ),
      body: Center(child: Text('Test')),
      floatingActionButton: FloatingActionButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: const Text('Back')),
    );
  }
}

我想我遗漏了一些明显的东西,但看不出它可能是什么...

更新:,以及具有路由映射的 main.dart 根应用程序:

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Named Routes',
      theme: ThemeData(scaffoldBackgroundColor: Colors.white),
      initialRoute: '/',
      routes: {
        '/': (context) => const MenuScreen(),
        '/clients': (context) => const ClientsScreen(),
        '/checkin': (context) => const CheckinScreen(),
             },
    );
  }
}

正如其他人已经在评论中指出的那样,需要一个 Material 小部件来包装 InkWell

原因:

The InkWell widget must have a Material widget as an ancestor. The Material widget is where the ink reactions are actually painted. This matches the material design premise wherein the Material is what is actually reacting to touches by spreading ink.

https://api.flutter.dev/flutter/material/InkWell-class.html

Ink effects: Material shows ink effects implemented by InkFeatures like InkSplash and InkHighlight below its children.

https://api.flutter.dev/flutter/material/Material-class.html

Material 小部件显示墨迹效果,例如其各自子项的 InkSplashInkHighlight。已经实现 Material 功能的小部件有 ScaffoldCard 等。这就是为什么需要其中一个作为祖先,如果没有,则需要 Material