Reputation: 59
after trying to add an icon to my list tile I constantly get this error:
════════ Exception caught by widgets library ═══════════════════════════════════
The following _TypeError was thrown building Alertbox(dirty, state: _AlertboxState#08465):
type 'Null' is not a subtype of type 'Icon'
The relevant error-causing widget was
Alertbox
lib/screens/team_screen.dart:58
When the exception was thrown, this was the stack
#0 _AlertboxState.build
package:trainings_app/widgets/alertbox_widget.dart:76
#1 StatefulElement.build
package:flutter/…/widgets/framework.dart:4691
#2 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4574
#3 StatefulElement.performRebuild
package:flutter/…/widgets/framework.dart:4746
#4 Element.rebuild
package:flutter/…/widgets/framework.dart:4267
...
════════════════════════════════════════════════════════════════════════════════
Here are the classes referenced by the error: team_screen
void newTeam() {
showDialog<Alertbox>(
context: context,
builder: (BuildContext context) {
return Alertbox('Namen auswählen:', addTeam);
},
);
}
alertbox_widget: the error gets caused by "onSubmitted" inside the TextField
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:trainings_app/config/palette.dart';
class Alertbox extends StatefulWidget {
final String title;
final Function(String, Icon) parseText;
const Alertbox(this.title, this.parseText);
@override
_AlertboxState createState() => _AlertboxState(title, parseText);
}
class _AlertboxState extends State<Alertbox> {
final String title;
final Function(String, Icon) parseText;
final textController = TextEditingController();
_AlertboxState(this.title, this.parseText);
var iconChoice;
List icons = [
Icons.sports_volleyball_outlined,
Icons.sports_handball_outlined,
Icons.sports_baseball_outlined,
];
@override
void dispose() {
textController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Dialog(
backgroundColor: Colors.transparent,
elevation: 0,
insetPadding: EdgeInsets.all(10),
child: Center(
child: Container(
decoration: new BoxDecoration(
borderRadius: new BorderRadius.all(const Radius.circular(20)),
color: Colors.white,
),
padding: const EdgeInsets.all(16.0),
child: SizedBox(
height: 100,
child: Column(
children: [
Text(
title,
style: TextStyle(
fontSize: 18,
),
),
Row(
children: [
DropdownButton(
value: iconChoice,
onChanged: (newIcon) {
setState(() {
iconChoice = newIcon;
});
},
items: icons.map((icon) {
return DropdownMenuItem(
value: icon,
child: Icon(icon),
);
}).toList(),
),
SizedBox(width: 12),
Expanded(
child: TextField(
onSubmitted: parseText(textController.text, iconChoice),
autofocus: true,
textAlign: TextAlign.center,
controller: textController,
),
),
SizedBox(width: 12),
ElevatedButton(
onPressed: () {
parseText(textController.text, iconChoice);
},
child: const Icon(CupertinoIcons.checkmark),
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Palette.orange),
),
),
SizedBox(width: 8),
],
),
],
),
),
),
),
);
}
}
I hope anyone can help me or has some kind of solution/work-a-round that can help fix that problem
Upvotes: 0
Views: 592
Reputation: 1934
So it took me a while to figure out whats the problem, but I think I got it.
I don't know exactly your planned functionality - for e.g. when the fields are empty (text and/or icon), are you doing any validation? You should probably catch that with deactivating the button or displaying an error message. But apart from that:
// method which is called when clicking the submit button
addTeam(String text, Icon icon) {
// do whatever you do in here
log('$text $icon');
}
class Alertbox extends StatefulWidget {
// you dont need to pass the title to the state, you can access it via
// widget.title, same for the onParseText method
final String title;
final Function(String, Icon) onParseText;
const Alertbox(this.title, this.onParseText);
@override
_AlertboxState createState() => _AlertboxState();
}
class _AlertboxState extends State<Alertbox> {
final textController = TextEditingController();
// you somehow messed up Icon and IconData, try to define which type it is
// it can be null since there is no default icon set
Icon? iconChoice;
// also define the type for the list
List<Icon> icons = [
Icon(Icons.sports_volleyball_outlined),
Icon(Icons.sports_handball_outlined),
Icon(Icons.sports_baseball_outlined),
];
@override
void dispose() {
textController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Dialog(
backgroundColor: Colors.transparent,
elevation: 0,
insetPadding: EdgeInsets.all(10),
child: Center(
child: Container(
decoration: new BoxDecoration(
borderRadius: new BorderRadius.all(const Radius.circular(20)),
color: Colors.white,
),
padding: const EdgeInsets.all(16.0),
child: SizedBox(
height: 100,
child: Column(
children: [
Text(
widget.title,
style: TextStyle(
fontSize: 18,
),
),
Row(
children: [
// you can define the value type of the Dropdown, set it
// to Icon
DropdownButton<Icon>(
value: iconChoice,
onChanged: (newIcon) {
setState(() {
iconChoice = newIcon;
});
},
items: icons.map((icon) {
return DropdownMenuItem(
value: icon,
child: icon,
);
}).toList(),
),
SizedBox(width: 12),
Expanded(
child: TextField(
onSubmitted: (text) {
// this is what causes the error.
// you have to check if iconChoice is null
// I'm not really sure why you use onSubmitted
// here since you already have the submitbutton?
if (iconChoice != null) {
widget.onParseText(text, iconChoice!);
}
},
autofocus: true,
textAlign: TextAlign.center,
controller: textController,
),
),
SizedBox(width: 12),
ElevatedButton(
onPressed: () {
// you need to make sure iconChoice is not null
// before calling that method. Use some kind of
// validation here, like mentioned above
widget.onParseText(textController.text,
iconChoice!);
},
child: const Icon(CupertinoIcons.checkmark),
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Colors.orange),
),
),
SizedBox(width: 8),
],
),
],
),
),
),
),
);
}
}
Upvotes: 1