Dropdown Menu based on List, A non-null String must be provided to a Text widget - flutter

I am trying to generate a list of dropdown options for my user. I have created a custom model to use and here it is:
class UserFontModel {
String fontFamily;
FontWeight fontWeight;
UserFontModel({this.fontFamily, this.fontWeight});
}
I then create an instance here:
List<UserFontModel> _fonts = [
UserFontModel(fontFamily: 'Bold', fontWeight: FontWeight.w700),
UserFontModel(fontFamily: 'Medium', fontWeight: FontWeight.w500),
UserFontModel(fontFamily: 'Regular', fontWeight: FontWeight.w400),
UserFontModel(fontFamily: 'Light', fontWeight: FontWeight.w300),
UserFontModel(fontFamily: 'Thin', fontWeight: FontWeight.w100),
];
I then create a dropdown menu with the items based on the above list:
new DropdownButton<String>(
hint: Text('Style'),
items: _fonts.map((fonts) => DropdownMenuItem<String> (
child: Container(
width: MediaQuery.of(context).size.width * 0.2,
child: Text(fonts.fontFamily, style: TextStyle(fontWeight: fonts.fontWeight),),
),
)).toList(),
onChanged: (String _) {
setState(() {
print(_);
});
},
),
But for some reason (probably a simple one that i'm missing), I can't work out why i'm getting the error:
A non-null String must be provided to a Text widget.
Any thoughts?

Well, my obvious thought is: post a minimal compilable example, with the full error message.
But another thought that might actually help you to find the mistake yourself is: don't make programming hard on yourself. You are human. Let the machine do the hard work, that is the way we should do this. You want to make sure you never accidentally have a null value in your models? Then write the model so a null value is not possible without your compiler telling you exactly where you failed at compile time:
class UserFontModel {
final String fontFamily;
final FontWeight fontWeight;
const UserFontModel({#required this.fontFamily, #required this.fontWeight})
: assert(fontFamily != null),
assert(fontWeight != null);
}
This class is not instatiable without both fontFamily and fontWeight given, it will warn you at runtime, if you gave one and it was null and it makes sure you cannot accidentally change the fields after they have been checked to be correct. The point here is: this is your compiler. the machine does the work for you. As it should be.
This will not fix your actual problem, but it should fix your problem of not finding your actual problem.

Related

Is it okay to extend the Flutter built-in TextStyle class with my own custom methods?

Is there a problem if I extend some of the framework's built-in classes, specifically TextStyle, with my own extension methods? docs here
I'll layout an example of what I mean so that it resembles the actual implementation I'm using in my project - but not fully, it's just to be as clear and clean as possible:
In this example I'm declaring some common-use text styles (for context, in my project I have many many more), and later I'm extending the built-in flutter class TextStyle to have a faster and smoother implementation of further customization:
// some text styles I'll use across the whole app
const TextStyle titleLarge600 = TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.w600,
);
const TextStyle titleSmall500 = TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.w500,
);
const TextStyle bodyRegular400 = TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.w400,
);
// ...
//* Here it comes
extension CopyWithStyles on TextStyle {
/// Copy with [MyColors.primaryFontColor] color.
TextStyle get primaryColor => copyWith(color: MyColors.primaryFontColor);
/// Copy with [MyColors.accentColor] color.
TextStyle get accentColor => copyWith(color: MyColors.accentColor);
// ... several colors later
/// Copy with [TextDecoration.underline] decoration.
TextStyle get underline => copyWith(decoration: TextDecoration.underline);
/// Copy with [TextStyle.letterSpacing] of 0.4.
TextStyle get withLetterSpacing => copyWith(letterSpacing: 0.4);
// etc ...
}
This allows me to later just import these styles and methods and implement them in my Text widgets:
// ...
Text('Some title', style: titleSmall500.primaryColor),
... and even concatenate them:
// ...
Text(
'Some action here',
style: bodyRegular400.accentColor.underline.withLetterSpacing, // ← THIS WORKS! it has no limits really
),
I'm amazed as to how flexible extension methods are, but in this particular case (extending TextStyle) I'm wondering about performance issues, and compatibility with the framework, or if maybe I'm missing something and actually should not do this.
For the moment I'm not experiencing any issues. Still, I'm wondering if there could be any potential problems. Is there a problem if I implement something like this in my projects? Is there something I'm not considering and should take into account in the future?
TY

Is it possible to supply a default value to a Text widget?

As the question states, I would like to supply a default value to a Text Widget. I have four Text widgets. I use a variable in each Text Widget to display data. There is a chance that some data may not exist depending on the user and I would like to be able to default these Text Widgets to 0 if the value doesn't exist to prevent an error. Is this possible? Thanks!
Below is how it is currently.
Text(
'\$${quarter['data'][0].funds}',
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold),
),
You can provide a default value using the ?? operator, which returns the expression on its left unless that expression’s value is null, in which case it evaluates and returns the expression on its right (and you might need to add question marks for conditional property access in case quarter['data'] and quarter['data'][0] are nullable):
Text(
'\$${quarter['data']?[0]?.funds ?? 0}',
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
),
)
To safely access the funds at an index of the quarter['data'] list, you can create a helper method:
int fundsAt(int index) {
// This will return 0 if no element exists at the given index
return index >= 0 && index < quarter['data'].length
? quarter['data'][index].funds
: 0;
}
Here is the example of using fundsAt():
Text(
'\$${fundsAt(0)}',
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
),
)
You can try something like this :
'\$${quarter['data'][0].funds ?? 0}'
You can try these:
If the value can be null, then you can try this:
Text(myNullableData ?? "Default value");
Text(myNullableData == null ? "" : "Default value");
The ?? operator use your value if it is not null. If yes, it will use the default value you want.
Otherwise if some data may not exist depending means that the variable can be just an empty string: '""', then you can use the ?: operator:
Text(myData == "" ? "Default value" : myData);

Which one is performance wise better Text or extracted TextWidget function?

In my flutter code when I am creating an UI lot of places using Text widget. So I converted this Text widget into a function and calling everywhere? Text widget also including some styling. So calling the function or calling the Text widget is better (execution speed)?
Example code:
Text('Time left to Entrance exam',style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w400,
color: Colors.black
),);
or
Text buildText(String text,double fontSize, Color color) {
return Text(text,
style: TextStyle(
fontSize: fontSize,
color: color
),);
}
TextWidget function is more useful than multiple texts. It's absolutely a good practice and if any changes need you can able to change centrally and it's time-saving with clean code. You do not get the execution speed issue. And more important things, in both widget and function you just call a single Text widget. That's why there is no performance issue. You go for the second one for good practice.

Is there any way of using Text with spritewidget in Flutter?

I'm developing a game in Flutter with spritewidget library. I'd like to know if is it possible to use text inside a SpriteWidget.
I know i can use regular Flutter widgets but i need that the text size is relative to SpriteWidget so it can be consistently shown in different screen sizes.
I have searched library documentation but i haven't found anything related to text render.
Any suggestion would be appreciated!!
You can absolutely use text inside a SpriteWidget. There is the Label node for that particular purpose. If you need more advanced text rendering, you can use the code from the Label as your starting point.
Example:
Label label = Label(
'My text label',
textAlign: TextAlign.center,
textStyle: new TextStyle(
fontFamily: 'Orbitron',
letterSpacing: 10.0,
color: Colors.white,
fontSize: 24.0,
fontWeight: FontWeight.w600
)
);
addChild(label);

Flutter text not rendering correctly in some cases

I am developing a flutter app to display speed itself. But sometime, the speed isn't rendered correctly in the UI. This doesn't happen always but happens say 5-10% of the time.
I tried to add another text field, with lesser size below it(just to debug), and the same text renders there correctly.
2 screenshots - One correct and one with the bug
I am using a column widget to display the text and this is how I am building the children list:
List<Widget> children = [];
children.add(Container(
child: Text(listenerSpeedText,
style: TextStyle(color: Colors.lightGreen, fontSize: 100.00)),
padding: EdgeInsets.only(bottom: 5.00)));
children.add(Text(
'digitalSpeed: ' + listenerSpeedText,
style: TextStyle(
color: Colors.red,
fontSize: 25.00,
),
));
return children;
Any help would be appreciated. I am not sure what is going on. Do I need to give extra width or height to container?