buildTextSpan method
TextSpan
buildTextSpan({
- required BuildContext context,
- TextStyle? style,
- required bool withComposing,
override
Builds TextSpan from current editing value.
By default makes text in composing range appear as underlined. Descendants can override this method to customize appearance of text.
Implementation
@override
TextSpan buildTextSpan(
{required BuildContext context,
TextStyle? style,
required bool withComposing}) {
final provider = Data.maybeOf<_ChipProvider<T>>(context);
final theme = ComponentTheme.maybeOf<ChipInputTheme>(context);
final spacing = theme?.spacing ?? 4.0;
if (provider != null) {
final bool composingRegionOutOfRange =
!value.isComposingRangeValid || !withComposing;
if (composingRegionOutOfRange) {
List<InlineSpan> children = [];
String text = value.text;
StringBuffer buffer = StringBuffer();
for (int i = 0; i < text.length; i++) {
int codeUnit = text.codeUnitAt(i);
if (codeUnit >= _chipStart && codeUnit <= _chipEnd) {
// Flush buffer
if (buffer.isNotEmpty) {
children.add(TextSpan(style: style, text: buffer.toString()));
buffer.clear();
}
T? chip = _chipMap[codeUnit - _chipStart];
Widget? chipWidget =
chip == null ? null : provider.buildChip(context, chip);
if (chipWidget != null) {
bool previousIsChip = i > 0 &&
text.codeUnitAt(i - 1) >= _chipStart &&
text.codeUnitAt(i - 1) <= _chipEnd;
bool nextIsChip = i < text.length - 1 &&
text.codeUnitAt(i + 1) >= _chipStart &&
text.codeUnitAt(i + 1) <= _chipEnd;
children.add(ChipSpan<T>(
value: chip as T,
alignment: PlaceholderAlignment.middle,
child: Padding(
padding: EdgeInsets.only(
left: previousIsChip
? spacing / 2
: i == 0
? 0
: spacing,
right: nextIsChip ? spacing / 2 : spacing,
),
child: chipWidget,
),
));
}
} else {
buffer.writeCharCode(codeUnit);
}
}
// Flush remaining buffer
if (buffer.isNotEmpty) {
children.add(TextSpan(style: style, text: buffer.toString()));
}
return TextSpan(style: style, children: children);
}
final TextStyle composingStyle =
style?.merge(const TextStyle(decoration: TextDecoration.underline)) ??
const TextStyle(decoration: TextDecoration.underline);
List<InlineSpan> children = [];
String text = value.text;
StringBuffer buffer = StringBuffer();
for (int i = 0; i < text.length; i++) {
int codeUnit = text.codeUnitAt(i);
if (codeUnit >= _chipStart && codeUnit <= _chipEnd) {
// Flush buffer
if (buffer.isNotEmpty) {
children.add(TextSpan(style: style, text: buffer.toString()));
buffer.clear();
}
T? chip = _chipMap[codeUnit - _chipStart];
Widget? chipWidget =
chip == null ? null : provider.buildChip(context, chip);
if (chipWidget != null) {
bool previousIsChip = i > 0 &&
text.codeUnitAt(i - 1) >= _chipStart &&
text.codeUnitAt(i - 1) <= _chipEnd;
bool nextIsChip = i < text.length - 1 &&
text.codeUnitAt(i + 1) >= _chipStart &&
text.codeUnitAt(i + 1) <= _chipEnd;
children.add(ChipSpan<T>(
value: chip as T,
alignment: PlaceholderAlignment.middle,
child: Padding(
padding: EdgeInsets.only(
left: previousIsChip
? spacing / 2
: i == 0
? 0
: spacing,
right: nextIsChip ? spacing / 2 : spacing,
),
child: chipWidget,
),
));
}
} else {
// Check if current index is within composing range
if (i >= value.composing.start && i < value.composing.end) {
// Flush buffer
if (buffer.isNotEmpty) {
children.add(TextSpan(style: style, text: buffer.toString()));
buffer.clear();
}
children.add(TextSpan(
style: composingStyle, text: String.fromCharCode(codeUnit)));
} else {
buffer.writeCharCode(codeUnit);
}
}
}
// Flush remaining buffer
if (buffer.isNotEmpty) {
children.add(TextSpan(style: style, text: buffer.toString()));
}
return TextSpan(style: style, children: children);
}
return super.buildTextSpan(
context: context, style: style, withComposing: withComposing);
}