I'm trying to nest a static class within another one, for tidy access when using the styles later. Desired result is to be able to access it like this:
OverviewTheme.text.boxName
However, I'm getting a 'boxName' not defined error upon trying the above.
How do I do it properly?
Please see the code:
class OverviewTheme {
static const Color secondaryColor = Color(0xFFFFFF00);
static const Color primaryColor = Color(0xFFFFFFFF);
static const Color backgroundColor = Color(0xFF555555);
static const _TextStyles text = _TextStyles();
}
class _TextStyles {
const _TextStyles();
static const TextStyle boxName =
TextStyle(fontSize: 11, fontWeight: FontWeight.bold);
static const TextStyle boxDescription = TextStyle(fontSize: 10);
static const TextStyle boxNumber =
TextStyle(fontSize: 10, fontStyle: FontStyle.italic);
}
Static members of a particular class are accessed at the class level, not the object level. So, you can't access boxName.
Related
GetX: Color Model Error
I separate the Model and Controller classes.
model. dart:
import 'package:get/get. dart'; import 'package:flutter/material. dart';
class Model { var name = "agus".obs; var color = Colors.red[700].obs; }
controller. dart:
import 'package:get/get. dart';
import '../models/models. dart';
class PersonController extends GetxController {
var models = Models();
void changeUpperCase() {
models.name.value = "testing";
}
}
main.dart:
var modelA = Get.put(OrangController());
body: Center(
child: Obx(() => Text(
"My name is ${modelA. models.name}",
style: TextStyle(fontSize: 35, color: modelA.models.color),
))),
floatingActionButton: FloatingActionButton(onPressed: () {
modelA. changeUpperCase();
})
In the VS Code IDE, I get an error at IDE:
The argument type 'Rx<Color?>' can't be assigned to the parameter type
'Color?'
When you write this line :
var color = Colors.red[700].obs;
This is not a just Color, it's an Rx<Color> observable that contains inside of it the Color value, it's equivalent to :
Rx<Color> color = Colors.red[700].obs;
So when you assign it directly to the color property like this:
// ...
style: TextStyle(fontSize: 35, color: modelA.models.color),
You're trying here to assign the wholeRx<Color> instead of only its value which is the Color, basically, you need to assign it like this:
// ...
style: TextStyle(fontSize: 35, color: modelA.models.color.value), // added .value here
Now the error should be gone and the code works normally.
How do you apply a method to a static variable from a class. There are certain built in classes in flutter that appear to do something like this.
class UITextStyle {
static const TextStyle body = TextStyle(fontSize: 17);
addColor(Color color) {
TextStyle style = this as TextStyle;
style.merge(TextStyle(color: color));
}
}
Which can then be called like this:
UITextStyle.body.addColor(Color.fromRGBA(0,0,0,1));
However I cannot call that method like that as firstly it is not static, and secondly if it were I would not be able to call it after declaring .body first and would only be able to call it at UITextStyle.addColor(...).
How is this achieved?
you can try this solution , the point is that addColor function is not defined to the TextStyle Type , so to achieve that you need to add this function to the TextStyle class by this extension :
extension TextStyleEx on TextStyle{
TextStyle addColor(Color color) {
return merge(TextStyle(color: color,fontWeight: FontWeight.w600));
}
}
and make this method return TextStyle so you can get instance from the merged ones , cause your static object is final so you can not receive new value on it.
and leave your class like this
class UITextStyle {
static const TextStyle body = TextStyle(fontSize: 17);
}
use this class and the saved static object to get new TextStyle with the old and the new TextStyles.
for test run this in main , will clear the previous example :
TextStyle mergedStyles = UITextStyl.body.addColor(Colors.black);
print(mergedStyles);
Thanks to the comments from #pskink I was eventually able to get this functioning.
class UITextStyle {
const UITextStyle(this.style);
final TextStyle style;
static const body = UITextStyle(TextStyle(fontSize: 17));
addColor(Color color) {
TextStyle textStyle = style;
return textStyle.merge(TextStyle(color: color));
}
}
In Dart extensions can have static members.
extension UITextStyle on TextStyle {
static const body = TextStyle(fontSize: 17);
TextStyle addColor(Color color) {
return this.merge(TextStyle(color: color));
}
}
UITextStyle.body.addColor(Color.fromRGBO(0, 0, 0, 1));
Missing concrete implementation of 'getter FontWeight.value'.
Try implementing the missing method, or make the class abstract.
'''
enum TitleWeight implements FontWeight {
regular(FontWeight.w400),
medium(FontWeight.w500),
semiBold(FontWeight.w600),
bold(FontWeight.w700),
extraBold(FontWeight.w800),
black(FontWeight.w900);
final FontWeight weight;
const TitleWeight(this.weight);
}
'''
This was simply solved by implementing the value Function, as such
/// Cinzel
enum TitleWeight implements FontWeight {
regular(FontWeight.w400),
medium(FontWeight.w500),
semiBold(FontWeight.w600),
bold(FontWeight.w700),
extraBold(FontWeight.w800),
black(FontWeight.w900);
#override
int get value => _weight.value;
final FontWeight _weight;
const TitleWeight(this._weight);
}
I have proxy object companyCustomColors:
class CustomColors {
final CompanyCustomColors companyCustomColors;
CustomColors(BuildContext context)
: companyCustomColors =
Theme.of(context).extension<CompanyCustomColors>() ?? defaultColors;
Color get vipColor => companyCustomColors.vipColor;
Color get linksColor => companyCustomColors.linksColor;
Color get linkPressedColor => companyCustomColors.linkPressedColor;
}
Is it possible to use some Dart features (proxy, mixin, delegate) to get rid of these getters (vipColor, linksColor, linkPressedColor), but still have IDE autocomplete suggestions for CustomColors?
This object used like this one:
Text('sample',
style: TextStyle(
color: CustomColors(context).vipColor,
height: lineHeight,
),
)
Other classes used in this example:
class CompanyCustomColors extends ThemeExtension<CompanyCustomColors> {
const CompanyCustomColors({
required this.vipColor,
required this.linksColor,
required this.linkPressedColor,
});
final Color vipColor;
final Color linksColor;
final Color linkPressedColor;
}
const CompanyCustomColors defaultColors = CompanyCustomColors(
vipColor: AppColors.orange,
linksColor: AppColors.blue,
linkPressedColor: AppColors.blue_pressed,
);
I know about the theme object "ThemeData" and i'm making use of that as well, but alas the need for extending it has arisen.
What I'm trying to accomplish is defining style sets to reference throughout my app. For example i have this
child: Text(
advisoryServiceStatus[item.status - 1],
style: TextStyle(
color: Color.fromRGBO(0, 0, 0, 0.6),
fontSize: 12,
fontWeight: FontWeight.w500),
),
and i want to move the TextStyle in a file so i can do something like
child: Text(
advisoryServiceStatus[item.status - 1],
style: extendedThemeConfig.textStyles.mutedText,
but i have troubled properly defining my style object. Here's what i tried. Maybe i shouldn't be using classes, but i haven't managed to define them as objects. (my understanding of the concepts is a bit shabby)
This is how i tried to define my extendedThemeConfig
class TextStyles {
final TextStyle mutedText = TextStyle(
color: Color.fromRGBO(0, 0, 0, 0.6),
fontSize: 12,
fontWeight: FontWeight.w500);
}
class ExtendedThemeConfig {
TextStyles textStyles;
}
const extendedThemeConfig = ExtendedThemeConfig;
Why your approach doesn't work
It probably does work, but features like hot-reload aren't supported, because you introduce global state to your app, which is often not what you want.
So, how to do it better?
I already answered a similar question here more elaborately, but here's a version adapted to your problem:
Because Flutter is open source, we can just look at how the Theme is implemented and copy that code to create a custom widget that functions just like a Theme.
Here's a boiled-down version:
#immutable
class MyThemeData {
MyThemeData({
this.mutedText,
});
final TextStyle mutedText;
}
class MyTheme extends StatelessWidget {
MyTheme({
Key key,
#required this.data,
#required this.child,
}) : super(key: key);
final MyThemeData data;
final Widget child;
static MyThemeData of(BuildContext context) {
return (context.ancestorWidgetOfExactType(MyTheme) as MyTheme)?.data;
}
#override
Widget build(BuildContext context) => child;
}
Now, you can just wrap the MaterialApp in a MyTheme widget:
MyTheme(
data: MyThemeData(
mutedText: ...,
),
child: ... (here goes the MaterialApp)
)
Then anywhere in your app, you can write MyTheme.of(context).mutedText.
You can adapt the MyThemeData class to your needs, storing anything you want.