Flutter中Hero与Ink.image组合报错:未找到Material组件
问题解决:Hero与Ink.image结合时的"未找到Material组件祖先"错误
问题原因
Hero组件执行过渡动画时,会把内部Widget临时挂载到全局Overlay层,此时该Widget脱离了原页面Scaffold的Material上下文,导致Ink.image依赖的Material祖先不存在,触发断言错误。
解决方案
在Hero的直接子节点外层包裹透明Material组件,为Ink.image提供必要的Material上下文,同时不影响原有视觉效果和水波纹交互。
修改后的完整代码
import 'package:flutter/material.dart'; void main() => runApp(const App()); class App extends StatelessWidget { const App({super.key}); @override Widget build(BuildContext context) { return MaterialApp( theme: ThemeData.light().copyWith( splashColor: Colors.amber.withAlpha(150), highlightColor: Colors.transparent, ), home: const Home(), ); } } class Home extends StatelessWidget { const Home({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text("Home"), ), body: Center( child: InkWell( onTap: () { Navigator.of(context).push( MaterialPageRoute( builder: (context) => const Detail(), ), ); }, child: SizedBox( width: 100, height: 100, child: Hero( tag: "tag", // 包裹透明Material,为Ink.image提供上下文 child: Material( type: MaterialType.transparency, child: Ink.image( image: const NetworkImage( "https://storage.googleapis.com/cms-storage-bucket/0dbfcc7a59cd1cf16282.png", ), ), ), ), ), ), ), ); } } class Detail extends StatelessWidget { const Detail({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text("Detail"), ), body: Hero( tag: "tag", // 同样包裹透明Material child: Material( type: MaterialType.transparency, child: Ink.image( image: const NetworkImage( "https://storage.googleapis.com/cms-storage-bucket/0dbfcc7a59cd1cf16282.png", ), ), ), ), ); } }
关键修改点
- 在Hero的
child外层添加Material(type: MaterialType.transparency):透明类型的Material不会改变原有UI视觉效果,但能为Ink组件提供所需的Material上下文,解决动画期间的断言错误。 - 保留原有InkWell和Ink.image结构,确保水波纹点击效果不受影响。
效果验证
修改后,Hero过渡动画正常执行,点击图片的水波纹效果完全保留,控制台不再出现"未找到Material组件祖先"的错误。
内容的提问来源于stack exchange,提问作者Burhan Khanzada
相关产品推荐
相关产品推荐

