Invalid Constant Value using variable as parameter - dart

var textSize = 10.0;
// or
double textSize = 10.0;
into Text Widget of Flutter
child: const Text('Calculate Client Fees',
style: TextStyle(fontSize: textSize),)
Here it is giving error
Invalid Constant Value
Do we have to compulsory use const value? Why can not we use var or double?

You are declaring your Text widget as a const, which requires all of its children to be const as well. If you want to fix this, you should not use a const Text widget in this case as you want to pass a non-const variable.
The reason for this is that Flutter uses the const keyword as an idicator for a widget to never rebuild as it will get evaluated at compile time and only once. Hence, every part of it has to be constant as well.
double textSize = 10.04;
// ...
child: Text('Calculate Client Fees', style: TextStyle(fontSize: textSize))
Read more about it in this article.

Don't use the const keyword if you are not using fixed values.
For example, in the case of Text, if its string is constant like Text("something here") then we should use the const but if the string of Text is dynamic then don't use const before Text widget.
const Text("something") and Text(anyVariabale)
The same is the case for all widgets.

As #creativecreatorormaybenot said you are using const Text() which is why you have to have a const value there.
You can either use
const double textSize = 10.0;
or
const textSize = 10.0;
Just like this case.
Padding(
padding: const EdgeInsets.all(value), // this value has to be a `const` because our padding: is marked const
child: Text("HI there"),
);
Padding(
padding: EdgeInsets.all(10), // any double value
child: Text("HI there"),
);

In dart when you pass something as a parameter in a const constructor, the compiler makes sure that the value set as default is not changed during the execution of the code.
Hence, the Invalid constant value warning.
To resolve this issue you should remove the const keyword from the in front of the Text.

child: const Text('Calculate Client Fees',
style: TextStyle(fontSize: textSize),)
should be:
child: Text('Calculate Client Fees',
style: TextStyle(fontSize: textSize),)

You should remove the keywords const
When it is used, it put the widget into the cache.
And you can't wait for a value into your widget and put the widget again as a constance. When you want to do that, you should not put your widget constant.
So do that:
double textSize = 10.0;
child: Text('Calculate Client Fees', style: TextStyle(fontSize: textSize),)

Sometimes this can be tricky because the Text widget might not be the one which is const (where the error is displayed), but maybe its parent widget is const or the parent of that parent widget, etc. In that case it could be surprising and not immediate to spot the solution. For example:
const PrefLabel(
title: Text(
preferenceOptionTitle,
style: Get.textTheme.headline5!,
maxLines: 3,
),
subtitle: Text(preferenceOptionDescription),
),
In this case the Text is not marked with const because the PrefLabel is already const. The corrected one which passes linting: const is moved to the subtitle
PrefLabel(
title: Text(
preferenceOptionTitle,
style: Get.textTheme.headline5!,
maxLines: 3,
),
subtitle: const Text(preferenceOptionDescription),
),

if you want to use the var or double textSize = 10.0; then the text widget must not be a const. remove the const before the Text()
child: Text('Calculate Client Fees', style: TextStyle(fontSize: textSize),)

The simplest solution is to Just remove the const keyword.
replace with:
child: const Text('Calculate Client Fees',
style: TextStyle(fontSize: textSize),)

Related

Is there a more optimal way to space widgets within a column?

So i'm emulating an old app I have where the UI looks like this
Currently i'm focused on creating the UI layout for the purple side bar, I did that by creating a Container with a purple background. Within the container I created a column with multiple children and just used an empty SizedBox to create distance between one widget from another.
import 'package:flutter/material.dart';
class SignInPage extends StatelessWidget {
const SignInPage({super.key});
#override
Widget build(BuildContext context) {
return Scaffold(
// appBar: AppBar(
// title: Text('Sample Text'),
// elevation: 5.0,
// ),
body: _buildContent(),
);
}
Widget _buildContent() {
// private method
return Container(
color: Colors.deepPurpleAccent,
padding: EdgeInsets.all(16.0),
child: Column(
// crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
color: Colors.orange,
child: SizedBox(
height: 100.0,
width: 80.0,
),
),
SizedBox(
height: 140.0,
),
Container(
color: Colors.red,
child: SizedBox(
height: 50.0,
width: 80.0,
),
),
SizedBox(
height: 8.0,
),
Container(
color: Colors.purple,
child: SizedBox(
height: 50.0,
width: 80.0,
),
),
],
),
);
}
}
I'm quite new to flutter so i'm wondering if there's a better way to structure my layout of the side bar? Also to think in the future, since the name "BagTrack" Is on the same level as "Analytic Overview" Should that just be one giant row"?
Actual answer
Method 1
#Mahfuzur Rahman answer is good, but to actually answer your question about other ways. Flex widgets (Column and Row extend the Flex widget), have both mainAxisAlignment and crossAxisAlignment, they can be used to align them more easily between different devices/screens sizes.
So maybe grouping your red and purple boxes in a Column with mainAxisSize set to MainAxisSize.min, and aligning the surrounding column with a specific size.
https://api.flutter.dev/flutter/widgets/Column-class.html
Method 2
Another way, if you would like some widget to occupy some percentage amount of space from it's parent, I suggest you look into Expanded widget, Flexible widget.
Method 3
Or even FractionallySizedBox could be a good widget for you, but then I would also look at this LayoutBuilder widget to solve the potential Unbounded Height/Width exception.
Second smaller question
It's entirely up to you to decide about your second question concerning the giant row. I wouldn't do it though. Probably would use a const SizedBox or const EdgeInsets (for Padding) and keep them at the same height this way.
Just complementing Flutter knowledge
PS: Since you are new to Flutter. As a suggestion for future performance: avoid the Container widget as much as you know, there are a lot of simpler widgets like SizedBox, ColoredBox, DecoratedBox and Padding that you can use in its place that could be marked as const sometimes and be less expensive.
For understanding final and const:
final is a variable that cannot be reassigned by accident inside your code. When you instantiate it you give it a value and that's it. (Using late changes that a bit but not much);
const is a variable assigned by the compiler, if you are familiar with C it's like #define but there is a little difference, every time you say const EdgeInsets.all(8) for example, the compiler will detect that and use the same variable, so you don't have to remember a specific constant variable name.
Yes there is. But using SizedBox also wont hurt.
I usually Prefer ListTile for each element in the drawer.
ListTile(
leading: GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {},
child: Container(
width: 48,
height: 48,
padding: const EdgeInsets.symmetric(vertical: 4.0),
alignment: Alignment.center,
child: const CircleAvatar(),
),
),
title: const Text('title'),
dense: false,
)

Changing the color and styling of the Button in Flutter

I have migrated to Flutter 2.0 which is just the new release now. In my project I have used Flat Buttons but it got deprecated now in Flutter 2.0 and the suggestion pop up to use Text Button instead of Flat Buttons.
Now the problem is in Flat Buttons there are option directly to set the properties of button such as color, padding etc. but when I replaced it with Text Button there is error in using this properties. I have checked the documentation and found that there is the property of style: ButtonStyle(backgroundcolor: ____________). But when I have put Colors.blue in the backgroundcolor property it gives me error.
So I want to know that how is the behaviour of Buttons in Flutter 2.0 and how we can style the Buttons?
My snippet of code is here in which I want to style the button.
Container(
width: 200.0,
child: TextButton(
style: ButtonStyle(), // I want to style this.
onPressed: () => Navigator.pushNamed(context, SignupPage.id),
/*color: Colors.blue,
padding: const EdgeInsets.all(10.0),*/ //Commented code is deprecated in Flutter 2.0
child: Text(
'Create Account',
style: TextStyle(color: Colors.white, fontSize: 16.0),
),
The style argument with a backgroundcolor is the way to do it, but does not take a Color object, its type is MaterialStateProperty<Color?>? so you should provide an object of that type.
documentation is here https://api.flutter.dev/flutter/material/TextButton-class.html
and here https://api.flutter.dev/flutter/material/ButtonStyle-class.html
Buttons now have a state, so you have to define the colors for each state:
you can define one color for all the states.
ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.green),
you can define a different color for each state.
ButtonStyle(
backgroundColor: MaterialStateProperty.resolveWith(
(Set states) {
if (states.contains(MaterialState.pressed))
return Theme.of(context).colorScheme.primary.withOpacity(0.5);
return null; // Use the component's default.
},
),
),

How to customize numberpicker in Flutter?

I implemented numberpicker in my app.
I would like to modify the size of the numbers and the color of both highlighted value and those who are not. I managed to modify the highlighted ones wrapping it in the Theme widget and modifing the accentcolor, but don't know how I can do the other customizations?
Theme(
data: Theme.of(context).copyWith(
accentColor: Colors.red,
),
child: NumberPicker.integer(
initialValue: _currentPickerValue,
minValue: 0,
maxValue: 100,
onChanged: (newValue) =>
setState(() => _currentPickerValue = newValue)))
I digged into the code and here is something that I found
selectedStyle = themeData.textTheme.headline.copyWith(color: themeData.accentColor);
defaultStyle = themeData.textTheme.body1; This is ones which are not highlighted
to change the size or color or any other style attribute modifiy those style.
here is an example code:
final theme = Theme.of(context);
Theme(
data: theme.copyWith(
accentColor: Colors.black,// highlted color
textTheme: theme.textTheme.copyWith(
headline5: theme.textTheme.headline5.copyWith(..), //other highlighted style
bodyText2: theme.textTheme.headline5.copyWith(...), //not highlighted styles
)),
child: NumberPicker.integer(...),
);
Update your number picker package to the latest version.
new NumberPicker.integer(
...,
selectedTextStyle: TextStyle(...),
textStyle: TextStyle(...), //styles of the default text
)
Visit NumberPickec class for study properties.

Flutter AutoResizeTextView, setting high fontSize overflows

In Android, we can use AutoResizeTextView and give it any text size of our choice, it will not flow out of its constraints, I was looking for similar solution in Flutter.
I tried following,
Container(
color: Colors.blue,
constraints: BoxConstraints(maxHeight: 200.0, minWidth: 600.0),
child: Text("8", style: TextStyle(fontSize: 400.0)),
);
Here is the ugly output. So, how can I force the Text to always stay inside the Container no matter how much fontSize is given to it
Thanks to pskink,
I need to wrap the Text inside FittedBox which is further wrapped inside a Container. Here is the solution.
Container(
color: Colors.blue,
constraints: BoxConstraints(maxHeight: 200.0, minWidth: 600.0),
child: FittedBox(child: Text("8", style: TextStyle(fontSize: 400.0))),
);

How do I auto scale down a font in a Text widget to fit the max number of lines?

I'm trying to use BoxFit.scaleDown in a FittedBox's fit property to scale the font down in a Text widget to accommodate strings of varying length.
However, the below code will scale down the entire string and make it fit on one line, For the below example, I would like the font scaled down so that the string can fit on two lines (per maxLines property of the Text widget).
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Multi-Line Label Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Multi-Line Label Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
final textStyle = const TextStyle(fontSize: 28.0);
final text =
'Lorem Ipsum is simply dummy text of the printing and typesetting'
'industry. Lorem Ipsum has been the industry\'s standard dummy text'
'ever since the 1500s, when an unknown printer took a galley of type'
'and scrambled it to make a type specimen book.';
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new FittedBox(
fit: BoxFit.scaleDown,
child: new Text(
text,
maxLines: 2,
style: textStyle,
textAlign: TextAlign.center,
),
),
],
),
),
);
}
}
An easy drop-in solution is to use FittedBox with fit: BoxFit.scaleDown:
Container(
width: 100.0,
child: FittedBox(
fit: BoxFit.scaleDown,
// Optionally apply `alignment` to position the text inside the box:
//alignment: Alignment.topRight,
child: SizedBox(
child: Text('\$1,299.99'),
)
)
you can use the auto text package
https://pub.dartlang.org/packages/auto_size_text
after install it, just replace all of 'Text' to 'AutoSizeText' and you will find every things will be good :)
We got 2 ready-to-use solutions to this depending on the constraints you want to have.
1. Scale only
This solution works if you like how the layout looks on some reference screen size, want to treat the text area as a box and just scale up or down the entire box given other sized screens.
Take a reference screen. Lay everything out as intended. Find out the size of the box containing the text (by showing the render tree by pressing 't' during debug for instance). Then wrap the text containing box with a SizedBox of the same size as measured. Then wrap that with your FittedBox.
The restriction is basically that your text is laid out exactly the same way on all screens and you'll have the same aspect ratio for the text box.
2. Multiple references
Given a parent with variable size, first use a LayoutBuilder to get the parent's size during runtime, and then manually adjust the font size in the child text widget to make sure it fits.
The text layout is more fluid and the containing box can have different aspect ratios, but you'd have to check on as many screens sizes as the font size switches you have. Though it's easy to make sure that the text doesn't overflow at any screen size using widget tests
We can also create more complex but automatic means if there are more concrete examples of generalized use cases involving dependent font scaling
This happened in my app:
I solved by calculating the maximum number of chars shown in one line and reducing dynamically the Text FontSize if its string length is greater.
Get the char width of your text
First of all, I calculated the width of every char shown.
For doing that I needed the effective container width and the number of chars shown.
To get the screen width (that actually is the container width), I put my Text widget inside a LayoutBuilder:
new LayoutBuilder(builder: (context, constraint) {
//screen width got from the LayoutBuilder
double maxWidth = constraint.biggest.width;
//I'm going to change this dinamically
double fontSize = 33.0;
//return my widget
return new Text(
_brand.name,
maxLines: 1,
style: new TextStyle(fontSize: fontSize),
);
}
To get the chars shown before a new line, I put a big string in the Text and I manually counted how many chars were shown in one line. I put this value in a const (maxCharInOneLine) and then I was able to calculate the single char width: I divided the maximum witdh by maxCharInOneLine:
new LayoutBuilder(builder: (context, constraint) {
//screen width got from the LayoutBuilder
double maxWidth = constraint.biggest.width;
//chars shown manually counted
const int maxCharInOneLine = 17;
//single char width
int charWidth = (maxWidth / maxCharInOneLine).toInt();
//TO RUN IN DEBUG MODE
print("Char size with this screen and Text's TextStyle: " + charWidth.toString());
...
}
I runned the code above in the debug mode in order to get the charSize value, then I put is in a const and I removed that code that is useless at runtime.
Change dynamically the font
Now, with a constant char width and a variable container width (got from the LayoutBuilder) you can have every time the maximum number of chars that fits in one line.
new LayoutBuilder(builder: (context, constraint) {
const int charWidth=16;
//screen width got from the LayoutBuilder
double maxWidth = constraint.biggest.width;
//dinamically get the char number that fits in one line with this screen
int charsPerLine = (maxWidth / charWidth).toInt();
//if it doesn't fit in a line, reduce the fontSize
double fontSize = (_brand.name.length <= charsPerLine) ? 33.0 : 23.0;
return new Text(
_brand.name,
maxLines: 1,
style: new TextStyle(fontSize: fontSize),
);
}
The result:
My solution is not the best, but it works well in my case.
I'd like to get feedbacks. :)
EDIT Aug 2020: You can now simply use the library AutoSizeText
Just wrap your Text inside a FittedBox widget without setting any fit value.
SizedBox(
width: 10,
child: FittedBox(
child: Text('Your Text'),
),
)
Did you try using the Flexible widget
new Flexible(
child: new Text(
text,
style: textStyle,
textAlign: TextAlign.center,
),
),

Resources