Flutter Newb: I have a grid of image buttons on a menu screen. When clicking a button it animates into the 'leading' element of the new view's AppBar. That works as I was expecting it to. So far so good...
When I Navigator.pop() that 2nd view I get the error "No Material widget found."... The specific widget that could not find a Material ancestor was: _InkResponseStateWidget... (though the menu screen does reappear as expected
/// ...
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. I can't say I completely understand all the context and key stuff either :-)
The second 'screen's code is
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')),
);
}
}
I imagine I'm missing something obvious, but can't see what it might be...
Update:, and the main.dart root app with the routes map:
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(),
},
);
}
}
As others already pointed out in the comments, a
Material
widget is needed to wrap theInkWell
.Reason:
https://api.flutter.dev/flutter/material/InkWell-class.html
https://api.flutter.dev/flutter/material/Material-class.html
The
Material
widget displays ink effects likeInkSplash
andInkHighlight
of its respective children. Widgets already implementing theMaterial
functionality areScaffold
,Card
etc. Which is why one of these is needed as an ancestor, and if not,Material
is needed.