Skip to content

Instantly share code, notes, and snippets.

@arafaysaleem
Last active December 25, 2024 10:21
Show Gist options
  • Save arafaysaleem/2bbd846be58fa52a8b81554dd9b3bf94 to your computer and use it in GitHub Desktop.
Save arafaysaleem/2bbd846be58fa52a8b81554dd9b3bf94 to your computer and use it in GitHub Desktop.
Custom Text Wrapper For Flutter
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