Widget fails to render when a Stack widget is used
loongyeat opened this issue · comments
As title implies. Console shows flutter: Null check operator used on a null value
. To re-create:
class SomeWidget extends StatelessWidget {
const SomeWidget({Key? key}) : super(key: key);
static final _key = GlobalKey();
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(),
floatingActionButton: FloatingActionButton(
onPressed: () {
final exporter = _key.currentWidget as DynamicWidgetJsonExportor?;
final exportedJsonString = exporter?.exportJsonString();
if (exportedJsonString == null) {
return;
}
Navigator.of(context).push<void>(
MaterialPageRoute(
builder: (context) => const RendererWidget(exportedJsonString),
),
);
},
child: const Icon(Icons.copy),
),
body: DynamicWidgetJsonExportor(
key: _key,
child: _buildSimpleWidget(),
),
);
}
Widget _buildSimpleWidget() {
return Stack(
children: [
Icon(Icons.star),
Icon(Icons.abc),
],
);
}
}
class RendererWidget extends StatelessWidget {
const RendererWidget(this.json, {Key? key}) : super(key: key);
final String json;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(),
body: SafeArea(
child: FutureBuilder<Widget?>(
future: _buildWidget(context),
builder: (context, snapshot) {
if (snapshot.hasError) {
print(snapshot.error);
}
if (!snapshot.hasData) {
return Container();
}
return SizedBox.expand(
child: snapshot.data,
);
},
),
),
);
}
Future<Widget?> _buildWidget(BuildContext context) async {
return Future.delayed(const Duration(seconds: 1), () {
return DynamicWidgetBuilder.build(
json,
context,
DefaultClickListener(),
);
});
}
}
class DefaultClickListener implements ClickListener {
@override
void onClicked(String? event) {
print(event);
}
}
As title implies. Console shows
flutter: Null check operator used on a null value
. To re-create:class SomeWidget extends StatelessWidget { const SomeWidget({Key? key}) : super(key: key); static final _key = GlobalKey(); @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, appBar: AppBar(), floatingActionButton: FloatingActionButton( onPressed: () { final exporter = _key.currentWidget as DynamicWidgetJsonExportor?; final exportedJsonString = exporter?.exportJsonString(); if (exportedJsonString == null) { return; } Navigator.of(context).push<void>( MaterialPageRoute( builder: (context) => const RendererWidget(exportedJsonString), ), ); }, child: const Icon(Icons.copy), ), body: DynamicWidgetJsonExportor( key: _key, child: _buildSimpleWidget(), ), ); } Widget _buildSimpleWidget() { return Stack( children: [ Icon(Icons.star), Icon(Icons.abc), ], ); } } class RendererWidget extends StatelessWidget { const RendererWidget(this.json, {Key? key}) : super(key: key); final String json; @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, appBar: AppBar(), body: SafeArea( child: FutureBuilder<Widget?>( future: _buildWidget(context), builder: (context, snapshot) { if (snapshot.hasError) { print(snapshot.error); } if (!snapshot.hasData) { return Container(); } return SizedBox.expand( child: snapshot.data, ); }, ), ), ); } Future<Widget?> _buildWidget(BuildContext context) async { return Future.delayed(const Duration(seconds: 1), () { return DynamicWidgetBuilder.build( json, context, DefaultClickListener(), ); }); } } class DefaultClickListener implements ClickListener { @override void onClicked(String? event) { print(event); } }
I try your code, it seems it's ok. the "exportedJsonString" is
exportedJsonString: {"type":"Stack","alignment":"topStart","textDirection":"ltr","fit":"loose","clipBehavior":"hardEdge","children":[{"type":"Icon","data":"star","size":null,"color":null,"semanticLabel":null,"textDirection":null},{"type":"Icon","data":"ac_unit","size":null,"color":null,"semanticLabel":null,"textDirection":null}]}