Reputation: 12503
I get this error:
IconButton widgets require a Material widget ancestor
for about a second, then it goes away. It is complaining about an IconButton in one of my custom widgets. However the custom widget is placed in a page with a Scaffold
. So the error should not exist since the custom button is inside a Scaffold
material widget. When I wrap the usage of the button in its own tiny Scaffold
, all is resolved. Why do I get this error temporarily? Is wrapping the custom widget in a tiny Scaffold
considered a hack fix or an actual fix? All code and full error below:
Error:
The following assertion was thrown building IconButton(Icon, padding: EdgeInsets.zero, dirty):
No Material widget found.
IconButton widgets require a Material widget ancestor.
In material design, most widgets are conceptually "printed" on a sheet of material. In Flutter's material library, that material is represented by the Material widget. It is the Material widget that renders ink splashes, for instance. Because of this, many material library widgets require that there be a Material widget in the tree above them.
To introduce a Material widget, you can either directly include one, or use a widget that contains Material itself, such as a Card, Dialog, Drawer, or Scaffold.
The specific widget that could not find a Material ancestor was: IconButton
Icon
padding: EdgeInsets.zero
dirty
The ancestors of this widget were
VpBackButton
Align
alignment: centerLeft
dependencies: [Directionality]
renderObject: RenderPositionedBox#49b68 NEEDS-LAYOUT NEEDS-PAINT
Expanded
flex: 1
Row
direction: horizontal
mainAxisAlignment: center
crossAxisAlignment: center
textBaseline: alphabetic
dependencies: [Directionality]
renderObject: RenderFlex#19d87 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
GetMaterialApp
App
...
The relevant error-causing widget was
IconButton
lib/…/back_button/back_button_widget.dart:18
When the exception was thrown, this was the stack
#0 debugCheckHasMaterial.<anonymous closure>
package:flutter/…/material/debug.dart:30
#1 debugCheckHasMaterial
package:flutter/…/material/debug.dart:52
#2 IconButton.build
package:flutter/…/material/icon_button.dart:330
#3 StatelessElement.build
package:flutter/…/widgets/framework.dart:4701
#4 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4627
...
════════════════════════════════════════════════════════════════════════════════
It is complaining about my custom widget:
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:vepo/presentation/modules/view.dart';
import 'back_button_widget_controller.dart';
class VpBackButton extends VpView<VpBackButtonController> {
VpBackButton({this.onPressed}) {
Get.put(VpBackButtonController());
}
@required
final VoidCallback onPressed;
AnimationController animateController;
@override
Widget build(BuildContext context) {
return IconButton(
padding: const EdgeInsets.all(0.0),
icon: Icon(Icons.arrow_back_ios_rounded,
color: Colors.white.withOpacity(0.5)),
iconSize: 38,
onPressed: () {
controller.goBack(onPressed);
},
);
}
}
The page that the button is inside contains a Scaffold
which is a material widget:
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:keyboard_avoider/keyboard_avoider.dart';
import 'package:reactive_forms/reactive_forms.dart';
import 'package:vepo/presentation/themes/home_theme.dart';
import 'package:vepo/presentation/widgets/display/buttons/back_button/back_button_widget.dart';
import 'package:vepo/presentation/widgets/display/buttons/elevated_buttons/elevated_submit_button_widget.dart';
import 'package:vepo/presentation/widgets/display/containers/gradient_container_widget.dart';
import 'package:vepo/presentation/widgets/display/text/subtitle_1_widget.dart';
import 'package:vepo/presentation/widgets/forms/text_field/text_field_widget.dart';
import 'package:vepo/presentation/widgets/pages/gradient_page_scaffold_widget.dart';
import '../../../../assets.gen.dart';
import 'logged_out_email_controller.dart';
class LoggedOutEmailView extends GetView<LoggedOutEmailController> {
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomPadding: false,
body: ConstrainedBox(
constraints: BoxConstraints.tightFor(
height: MediaQuery.of(context).size.height),
child: VpGradientContainer(
beginColor: initialGradientColor,
endColor: endGradientColor,
child: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Expanded(
flex: 1,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 1,
child: Hero(
tag: 'logoHero',
child: Row(
crossAxisAlignment:
CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Expanded(
flex: 1,
child: Align(
alignment: Alignment.centerLeft,
child: VpBackButton())),
Expanded(
flex: 1,
child: Assets.images.logo.image()),
Expanded(flex: 1, child: Container()),
]),
),
),
],
)),
Upvotes: 2
Views: 2304
Reputation: 3100
The issue you're seeing is a known bug in Flutter involving a Hero
animation.
I see in your case that VpBackButton
is under a Hero
. If you remove the Hero
, you'll see the error is gone. As per the linked bug above, currently there's only a workaround, which you've already discovered by yourself and it is to wrap the content of the Hero
, in your case VpBackButton
, with a Material
widget.
child: Hero(
tag: 'logoHero',
child: Row( <--- wrap this with Material widget***************
crossAxisAlignment:
CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Expanded(
flex: 1,
child: Align(
alignment: Alignment.centerLeft,
child: VpBackButton())),
Upvotes: 1
Reputation: 1430
Since you wrapped VpBackButton
flexible in LoggedOutEmailView
, you cannot give a fixed size in VpBackButton
. logic error. It is fixed if you remove iconsize or expanded.
Upvotes: 0