Declare variables in build method or in class itself? - Flutter - flutter

Which is the correct usage? Also I'm confused about if we should do "extract method" or "extract widget"? Flutter recommends to extract widgets. But I'm not sure where should I extract widget?
class TopBarTitle extends StatelessWidget {
const TopBarTitle();
static const String title = 'FLASHCARDS';
static const String fontFamily = 'Itim';
#override
Widget build(BuildContext context) {
return Text(
title,
style: TextStyle(
fontSize: 18.sp,
color: Theme.of(context).iconTheme.color,
fontWeight: FontWeight.w500,
fontFamily: fontFamily,
),
);
}
}
or
class TopBarTitle extends StatelessWidget {
const TopBarTitle();
#override
Widget build(BuildContext context) {
const String title = 'FLASHCARDS';
const String fontFamily = 'Itim';
return Text(
title,
style: TextStyle(
fontSize: 18.sp,
color: Theme.of(context).iconTheme.color,
fontWeight: FontWeight.w500,
fontFamily: fontFamily,
),
);
}
}

The first one is preferred. build method is supposed to be called many times in a short time and you should keep it simple. In the second code, you're defining two variables every time the method gets called (of course it's a very cheap operation considering they're constant but still it should be prevented whenever possible).
And to answer your question about "extract method" or "extract widget", Flutter recommends "extract widget" since there are lot's optimizations applied in that case and it's easier to debug too. There are lot's of discussions about that which you can easily find by searching. For example read this one: https://stackoverflow.com/a/53234826/5204833

First one is preferred, it will be declare each time you reach to that class
There is problem with the second one each time the set is updating it will will declare those variables again and again

Related

Flutter responsive fontSize

I've got a file called text_styles.dart which contains many different TextStyles like that (without a class or something else):
TextStyle subheadingTextStyle = TextStyle(
color: blackColor,
fontSize: 20.0,
height: 1.7);
I call this TextStyle in other files with
style: subheadingTextStyle
Now I want to resize the font size depending on the screen size like described here: Flutter fontsize in web
So I changed my subheadingTextStyle:
TextStyle subheadingTextStyle = TextStyle(
color: blackColor,
fontSize: Responsive.isDesktop(context)
? 20
: Responsive.isTablet(context)
? 15
: 10,
height: 1.7);
But I get an error that the context is undefined (because I try to access context outside of its scope).
What's the best way to fix that? Or is there any other (better?) way to dynamically resize the font size depending on the screen size?
If u want to use your method what u described then u need to handle like this below
TextStyle subheadingTextStyle = TextStyle(
color: Colors.black,
fontSize: 20.0,
height: 1.7,
);
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Text(
'Hello!',
style: subheadingTextStyle.copyWith(
fontSize: Responsive.isDesktop(context)
? 20
: Responsive.isTablet(context)
? 15
: 10,
),
);
}
}
class Responsive {
static bool isMobile(BuildContext context) =>
MediaQuery.of(context).size.width < 730;
static bool isTablet(BuildContext context) =>
MediaQuery.of(context).size.width < 1190 &&
MediaQuery.of(context).size.width >= 730;
static bool isDesktop(BuildContext context) =>
MediaQuery.of(context).size.width >= 1190;
}
But my suggestion is: make responsive based on device using any of this packages
https://pub.dev/packages/flutter_screenutil
or
https://pub.dev/packages/sizer

Flutter assign Theme text style

I was wondering is there is a better way to assign a certain default text style of my Theme to a Text widget than this approach.
Text(
'Hello world',
style: Theme.of(context).textTheme.headline1,
),
I did assume there should be something like a separate Widget or a Text Method Text.headline1 or simply a style Command style: TextStyle.headline1.
But seems I have to go through the Theme.of(context) to get this.
Does anyone have a better solution?
I think yon can't escape some boilerplate. For me this approach looks cleanest
import 'package:flutter/material.dart';
class StyledText extends StatelessWidget {
final String text;
late final TextStyle? Function(BuildContext context)? getStyle;
StyledText.headline1(this.text, {Key? key}) : super(key: key) {
getStyle = (context) {
return Theme.of(context).textTheme.headline1;
};
}
StyledText.headline2(this.text, {Key? key}) : super(key: key) {
getStyle = (context) {
return Theme.of(context).textTheme.headline2;
};
}
// ...
#override
Widget build(BuildContext context) {
return Text(text, style: getStyle?.call(context));
}
}
And use the widget like this
StyledText.headline1("Hello world");
Theme.of returns the ThemeData value specified for the nearest BuildContext ancestor. If you don't use it, then you won't be able to access the theme configuration you may set and benefit from its advantages.
However, you can create a class called Styles where you can access the pre-defined colors, text styles and more:
class Styles {
static const Color primaryColor = Colors.blue;
static const TextStyle headline1 = TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
);
static const TextStyle bodyText1 = TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.normal,
);
}
Here is an example of using it:
Text(
'Hello world',
style: Styles.headline1,
)
You define all Your Theme Style in Main like this
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.purple,
textTheme: TextTheme(
headline1: TextStyle(
color: const Color(0xFF232323),
fontSize: 26.sp,
fontWeight: FontWeight.w500,
fontFamily: "Mont Regular",
),
),
)
Then use like this
Text("A cloud-agnostic solution for Project and HR Management",
style: Theme.of(context).textTheme.headline1)
You can use TextStyle directly:
Text(
'Hello world',
style: TextStyle(color: Colors.black, fontSize: 15.0), // Etc...
),
Theme.of(context) is a great way to go for a variety of reasons, like switching between light and dark themes. I like to create a variable for the theme and text theme to keep things clean and efficient.
Widget build(BuildContext context) {
final theme = Theme.of(context);
final textTheme = theme.textTheme;
return Column(
children: [
Text('Heading Text', style: textTheme.headline1),
Text('Caption Text', style: textTheme.caption),
Text('Body text...', style: textTheme.bodyText1),
],
);
}

How to write a function (in flutter-dart) so that it accepts certain parameters when we call that function?

This is my code:
Text ButtonText = Text(
_buttonText, style: TextStyle(
color: Colors.white,
fontFamily: 'San francisco',
//fontSize: 21.0.ssp,
letterSpacing: 2.0,
wordSpacing: 2.0
),
);
when I use this Text in my button widget, I want to set font size explicitly. How can I do that?
you can create a class for your situation we can call it customtext
here is an example code :
import 'package:flutter/material.dart';
class CustomText extends StatelessWidget {
final String text;
final double size;
final Color color;
final FontWeight weight;
// name constructor that has a positional parameters with the text required
// and the other parameters optional
CustomText({#required this.text, this.size,this.color,this.weight});
#override
Widget build(BuildContext context) {
return Text(
text,style: TextStyle(fontSize: size ?? 16, color: color ?? Colors.black, fontWeight: weight ?? FontWeight.normal),
);
}
}

Get ThemeData from static area

I am saving my Text Styles in seperate text_styles.dart file. When i want to use theme colors just like Theme.of(context).primaryColor, I cant reach ThemeData object from text_styles.dart .I solved my problem with this kind of solution but this is not good solution.
TextStyle kWelcomePageHeaderTextStyle(BuildContext context) => TextStyle(
fontFamily: "Courgette",
fontSize: 30.0,
color: Theme.of(context).primaryColor,
);
So, i need to get ThemeData from static area for use my Text Styles like this.
const kWelcomePageHeaderTextStyle = TextStyle(
fontFamily: "Courgette",
fontSize: 30.0,
color: [THEME_DATA_OBJECT_NEEDED].primaryColor,
);
Can I get ThemeData object from text_styles.dart or is there any better solution?
I found better solution with Dependency Injection. I registered the dependency which is BuildContext in MaterialApp.
void main() {
final GetIt sl = GetIt.instance;
runApp(MaterialApp(
theme: myLightTheme,
darkTheme: myDarkTheme,
builder: (BuildContext context, Widget widget) {
if (!sl.isRegistered<BuildContext>()) {
sl.registerSingleton<BuildContext>(context);
}
return HomePage();
},
));
Then I can get Theme on the static area
const kWelcomePageHeaderTextStyle = TextStyle(
fontFamily: "Courgette",
fontSize: 30.0,
color: Theme.of(sl.get<BuildContext>()).primaryColor,
);
Your app does not have a single, globally available theme. So you cannot get it.
Your app already has two themes out of the box (dark mode/light mode) and you can have many more. You can even have a different theme for a specific subtree in your build methods using the Theme widget. You can read more about it in the documentation.
Getting the Theme from the context is the preferred method.

Flutter/Dart: Cast int to double in Widget Param not working

I'm trying casting a int to double in flutter/dart at param fontSize from Text Widget but I have this exception:
"Another exception was thrown: type 'int' is not a subtype of type 'double' in type cast"
I have been follow the instructions here: Why can't I convert a Number into a Double? but that's not working yet.
here is Text inside my component widget:
class ButtonLogin extends MaterialButton {
ButtonLogin({this.fontSize, ...});
final fontSize;
...
#override
Widget build(BuildContext context){
double fontSizeDouble = (fontSize as num) as double;
...
Text(
label,
style: TextStyle(
fontSize: fontSizeDouble,
color: labelColor,
fontWeight: FontWeight.bold
),
),
...
}
Out from component I'm passing at param fontSize a Int value like this:
...
ButtonLogin(
backgroundColor: ColorsCustom.loginScreenUp,
labelColor: Colors.white,
label: 'Back to other session?',
fontSize: 16,
mOnPressed: () => _login(),
);
...
the ellipsis is just to indicate there is more of code, its not part of code.
I am not getting any error. An advice I can give you to avoid errors is to use data types in your code when you define variables.