Last active
December 25, 2024 10:21
-
-
Save arafaysaleem/2bbd846be58fa52a8b81554dd9b3bf94 to your computer and use it in GitHub Desktop.
Custom Text Wrapper For Flutter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/gestures.dart'; | |
import 'package:flutter/material.dart'; | |
// Helpers | |
import '../../helpers/constants/constants.dart'; | |
import '../../helpers/extensions/extensions.dart'; | |
class CustomText extends StatelessWidget { | |
final String text; | |
final TextAlign? textAlign; | |
final TextOverflow overflow; | |
final FontWeight? fontWeight; | |
final double? fontSize; | |
final double? lineHeight; | |
final bool? softWrap; | |
final int? maxLines; | |
final Color? color; | |
final List<Widget>? textSpans; | |
final TextStyle? style; | |
final bool isLink; | |
final VoidCallback? onLinkTap; | |
final bool useSecondaryFont; | |
final double? letterSpacing; | |
final String? fontFamily; | |
const CustomText( | |
this.text, { | |
super.key, | |
this.textAlign, | |
this.fontFamily, | |
this.textSpans, | |
this.lineHeight, | |
this.useSecondaryFont = false, | |
this.isLink = false, | |
this.onLinkTap, | |
this.overflow = TextOverflow.ellipsis, | |
this.fontWeight, | |
this.fontSize, | |
this.letterSpacing, | |
this.color, | |
this.style, | |
this.maxLines, | |
this.softWrap, | |
}); | |
const CustomText.heading( | |
this.text, { | |
super.key, | |
this.letterSpacing, | |
this.color, | |
this.maxLines, | |
this.useSecondaryFont = false, | |
this.fontSize = 28, | |
this.fontWeight = FontWeight.bold, | |
this.fontFamily, | |
}) : textAlign = null, | |
overflow = TextOverflow.ellipsis, | |
softWrap = null, | |
textSpans = null, | |
style = null, | |
isLink = false, | |
lineHeight = null, | |
onLinkTap = null; | |
const CustomText.title( | |
this.text, { | |
super.key, | |
this.color, | |
this.letterSpacing, | |
this.maxLines, | |
this.useSecondaryFont = false, | |
this.fontSize = 22, | |
this.fontWeight = FontWeight.w600, | |
this.fontFamily, | |
}) : textAlign = null, | |
overflow = TextOverflow.ellipsis, | |
softWrap = null, | |
textSpans = null, | |
style = null, | |
isLink = false, | |
lineHeight = null, | |
onLinkTap = null; | |
const CustomText.body( | |
this.text, { | |
super.key, | |
this.color, | |
this.letterSpacing, | |
this.maxLines, | |
this.useSecondaryFont = false, | |
this.fontSize = 16, | |
this.fontWeight, | |
this.fontFamily, | |
}) : textAlign = null, | |
overflow = TextOverflow.ellipsis, | |
softWrap = null, | |
textSpans = null, | |
style = null, | |
isLink = false, | |
lineHeight = null, | |
onLinkTap = null; | |
const CustomText.subtitle( | |
this.text, { | |
super.key, | |
this.color, | |
this.maxLines, | |
this.letterSpacing, | |
this.useSecondaryFont = false, | |
this.fontSize = 14, | |
this.fontWeight, | |
this.fontFamily, | |
}) : textAlign = null, | |
overflow = TextOverflow.ellipsis, | |
softWrap = null, | |
textSpans = null, | |
style = null, | |
isLink = false, | |
lineHeight = null, | |
onLinkTap = null; | |
const CustomText.label( | |
this.text, { | |
super.key, | |
this.color, | |
this.letterSpacing, | |
this.maxLines, | |
this.useSecondaryFont = false, | |
this.fontSize = 12, | |
this.fontWeight = FontWeight.w300, | |
this.fontFamily, | |
}) : textAlign = null, | |
overflow = TextOverflow.ellipsis, | |
softWrap = null, | |
textSpans = null, | |
style = null, | |
isLink = false, | |
lineHeight = null, | |
onLinkTap = null; | |
const CustomText.link( | |
this.text, { | |
required this.onLinkTap, | |
super.key, | |
this.color, | |
this.letterSpacing, | |
this.maxLines, | |
this.useSecondaryFont = false, | |
this.fontSize = 16, | |
this.fontWeight, | |
this.fontFamily, | |
}) : isLink = true, | |
textAlign = null, | |
overflow = TextOverflow.ellipsis, | |
softWrap = null, | |
textSpans = null, | |
lineHeight = null, | |
style = null; | |
factory CustomText.rich({ | |
required List<Widget> children, | |
String? text, | |
CustomText? textWidget, | |
double? letterSpacing, | |
TextAlign? textAlign, | |
Color? color, | |
bool useSecondaryFont = false, | |
FontWeight? fontWeight, | |
int? maxLines, | |
double? lineHeight, | |
double fontSize = 16, | |
}) { | |
assert( | |
text != null || textWidget != null, | |
'Text or textWidget must be provided', | |
); | |
assert( | |
children.every((element) => element is CustomText || element is SizedBox), | |
'Children must be CustomText or SizedBox', | |
); | |
return CustomText( | |
text ?? textWidget?.text ?? '', | |
textSpans: children, | |
textAlign: textWidget?.textAlign ?? textAlign, | |
useSecondaryFont: useSecondaryFont, | |
maxLines: textWidget?.maxLines ?? maxLines, | |
letterSpacing: textWidget?.letterSpacing ?? letterSpacing, | |
fontWeight: textWidget?.fontWeight ?? fontWeight, | |
lineHeight: textWidget?.lineHeight ?? lineHeight, | |
fontSize: textWidget?.fontSize ?? fontSize, | |
color: textWidget?.color ?? color, | |
); | |
} | |
CustomText copyWith({ | |
TextAlign? textAlign, | |
TextOverflow? overflow, | |
FontWeight? fontWeight, | |
double? fontSize, | |
bool? softWrap, | |
int? maxLines, | |
Color? color, | |
TextStyle? style, | |
bool? useSecondaryFont, | |
double? lineHeight, | |
double? letterSpacing, | |
String? fontFamily, | |
}) { | |
return CustomText( | |
text, | |
textAlign: textAlign ?? this.textAlign, | |
overflow: overflow ?? this.overflow, | |
fontWeight: fontWeight ?? this.fontWeight, | |
fontSize: fontSize ?? this.fontSize, | |
softWrap: softWrap ?? this.softWrap, | |
maxLines: maxLines ?? this.maxLines, | |
color: color ?? this.color, | |
style: style ?? this.style, | |
lineHeight: lineHeight ?? this.lineHeight, | |
useSecondaryFont: useSecondaryFont ?? this.useSecondaryFont, | |
letterSpacing: letterSpacing ?? this.letterSpacing, | |
fontFamily: fontFamily ?? this.fontFamily, | |
); | |
} | |
TextStyle _buildTextStyleFromArgs( | |
BuildContext context, { | |
CustomText? otherText, | |
}) { | |
return TextStyle( | |
fontSize: otherText?.fontSize ?? fontSize, | |
fontWeight: otherText?.fontWeight ?? fontWeight, | |
height: otherText?.lineHeight ?? | |
lineHeight ?? | |
context.textTheme.bodyMedium?.height, | |
fontFamily: (otherText?.fontFamily ?? fontFamily) ?? | |
(otherText?.useSecondaryFont ?? useSecondaryFont | |
? AppTypography.secondaryFontFamily | |
: null), | |
color: otherText?.color ?? color, | |
letterSpacing: otherText?.letterSpacing ?? letterSpacing, | |
); | |
} | |
TapGestureRecognizer _buildLinkTapRecognizer() { | |
return TapGestureRecognizer()..onTap = onLinkTap; | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Text.rich( | |
TextSpan( | |
text: text, | |
recognizer: isLink ? _buildLinkTapRecognizer() : null, | |
children: textSpans | |
?.map( | |
(e) => switch (e) { | |
CustomText(isLink: false) => TextSpan( | |
text: e.text, | |
style: e.style ?? | |
style ?? | |
_buildTextStyleFromArgs(context, otherText: e), | |
), | |
CustomText(isLink: true) => TextSpan( | |
text: e.text, | |
style: e.style ?? | |
style ?? | |
_buildTextStyleFromArgs(context, otherText: e), | |
recognizer: e._buildLinkTapRecognizer(), | |
), | |
_ => WidgetSpan(child: e), | |
}, | |
) | |
.toList() ?? | |
[], | |
), | |
textAlign: textAlign, | |
maxLines: maxLines, | |
overflow: overflow, | |
softWrap: softWrap, | |
style: style ?? _buildTextStyleFromArgs(context), | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment