Reputation: 1172
I need to create a custom text-widget in the Flutter. I have to change any color it accepts in the style with an opacity of 0.7. If it does not have a style, I have to show the color from the default style with an opacity of 0.7 .
My problem is creating a new text widget with the feature I described.
Upvotes: 1
Views: 888
Reputation: 31
Custom Text using Getx
class CustomText extends StatelessWidget {
final String text;
final FontWeight fontWeight;
final double fontSize;
final Color color;
final TextDirection textDirection;
final TextAlign textAlign;
final bool softWrap;
final FontStyle fontStyle;
CustomText({
Key? key,
required this.text,
this.fontWeight = FontWeight.normal,
this.fontSize = 14.0,
this.color = Colors.black,
this.textDirection = TextDirection.ltr,
this.textAlign = TextAlign.left,
this.softWrap = true,
this.fontStyle = FontStyle.italic,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Text(
text,
style: TextStyle(
fontWeight: fontWeight,
fontSize: fontSize,
color: color,
fontStyle: fontStyle,
),
textDirection: textDirection,
textAlign: textAlign,
softWrap: softWrap,
);
}
}
Using like this:
appBar: CustomAppBar(title: CustomText(text: "Home"),)
Upvotes: 0
Reputation: 1172
I could have used the widget Opacity
very easily, but due to the Flutter document
for Opacity
Widget (resource) and the high cost of re-rendering
the child, it was not necessary.
The whole problem could be solved by DefaultTextStyle
. You only need to pay attention to handling the context
, which is documented
in the code below.
Two modes are seen in the following code:
1- If TextStyle
is not defined
for your Text widget, it follows the default color at DefaultTextStyle.of.(context)
or Theme
and then manual Opacity value is also set.
2- If TextStyle
is defined
for your Text widget, it follows the defined color and its manual Opacity value is also set.
import 'package:flutter/material.dart';
const double OPACITY_VALUE = 0.7;
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const HomeWidget(),
);
}
}
class HomeWidget extends StatelessWidget {
const HomeWidget({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
/// ATTENTION: parent of this context is Material App .
return Scaffold(
body: Center(
child: Builder(builder: (context2) {
/// context2 is important because referred to parent , and parent is Scaffold .
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
/// color and textStyle of this text widget referred to current Theme or DefaultTextStyle .
Text(
'You have pushed the button this many times:',
style: DefaultTextStyle.of(context2).style.copyWith(
color: DefaultTextStyle.of(context2)
.style
.color!
.withOpacity(OPACITY_VALUE)),
),
const CustomizedTextWidget(color: Colors.purple),
],
);
}),
),
);
}
}
class CustomizedTextWidget extends StatelessWidget {
const CustomizedTextWidget({
Key? key,
required this.color,
}) : super(key: key);
final Color color;
@override
Widget build(BuildContext context) {
return Text(
'0',
style: TextStyle(color: color, fontSize: 32)
.copyWith(color: color.withOpacity(OPACITY_VALUE)),
);
}
}
Upvotes: 0
Reputation: 724
The working solution simply uses
ThemeData.primaryColor
for the configuration of default text color;TextStyle
passes to CustomTextWidget
, the default text color is used with an opacity of 0.7;TextStyle
passes to CustomTextWidget
, the textStyle is used with an opacity of 0.7.Codes here:
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
@override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: const HomeWidget(title: _title),
theme: ThemeData.light().copyWith(
// default text color
primaryColor: Colors.pink,
colorScheme: ColorScheme.fromSwatch().copyWith(
// change the appbar color
primary: Colors.green[800],
),
),
);
}
}
class HomeWidget extends StatelessWidget {
const HomeWidget({
Key? key,
required String title,
}) : _title = title,
super(key: key);
final String _title;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(_title),
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
CustomTextWidget(text: 'text does not have a style'),
CustomTextWidget(
text: 'text with passed black color style and fontSize 24',
textStyle: TextStyle(
fontSize: 24,
color: Colors.black
),
),
CustomTextWidget(
text: 'text with passed blue color style',
textStyle: TextStyle(
color: Colors.blue
),
),
],
),
);
}
}
class CustomTextWidget extends StatelessWidget {
final String text;
final TextStyle? textStyle;
const CustomTextWidget({Key? key, required this.text, this.textStyle}) : super(key: key);
@override
Widget build(BuildContext context) {
final TextStyle finalTextStyle = textStyle ?? const TextStyle();
final Color? finalColor = textStyle != null && textStyle!.color != null
? textStyle!.color
: Theme.of(context).primaryColor;
return Text(
text,
// it accepts in the style with an opacity of 0.7.
style: finalTextStyle.copyWith(color: finalColor!.withOpacity(0.7)),
);
}
}
Expected outcome:
Upvotes: 0
Reputation: 676
There are multiple ways to approach this problem:
You can make a function based Widget or a class based Widget:
Function based Widget:
Widget myCustomText({required String data, Color? customColor}) {
return Opacity(
opacity: 0.7,
child: Text(
data,
style: TextStyle(
color: customColor ?? Colors.black,
),
),
);
}
Another approach is making a class based widget:
class MyCustomText extends StatelessWidget {
final String data;
final Color? customColor;
const MyCustomText({Key? key, required this.data, this.customColor})
: super(key: key);
@override
Widget build(BuildContext context) {
return Opacity(
opacity: 0.7,
child: Text(
data,
style: TextStyle(color: customColor ?? Colors.black),
),
);
}
}
Here's how you can implement your custom text wherever required: // Code M:
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
//Widget based Implementation
myCustomTextWidget(data: "Hello world"),
myCustomTextWidget(data: "Hello Peter", customColor: Colors.amber),
//Class based implementation
MyCustomTextClassWidget(data: "Hello Spidey"),
MyCustomTextClassWidget(data: "Hello 007", customColor: Colors.orange,)
],
),
);
}
}
Explanation: Null(??) operator checks if whether the value is given or not and if not given, then it will used default value after it.
Conclusion: Using Class based Widget i.e. Approach Number 2 is more robust and using class based widget is recommended by Flutter Official Team. It is also rebuild freindly and highly performant.
Upvotes: 4