Merge pull request #2135 from abarth/improve_text_span
Improve TextSpan
This commit is contained in:
@@ -14,24 +14,24 @@ void main() {
|
||||
|
||||
void addAlignmentRow(FlexAlignItems alignItems) {
|
||||
TextStyle style = const TextStyle(color: const Color(0xFF000000));
|
||||
RenderParagraph paragraph = new RenderParagraph(new StyledTextSpan(style, <TextSpan>[new PlainTextSpan('$alignItems')]));
|
||||
RenderParagraph paragraph = new RenderParagraph(new TextSpan(style: style, text: '$alignItems'));
|
||||
table.add(new RenderPadding(child: paragraph, padding: new EdgeDims.only(top: 20.0)));
|
||||
RenderFlex row = new RenderFlex(alignItems: alignItems, textBaseline: TextBaseline.alphabetic);
|
||||
style = new TextStyle(fontSize: 15.0, color: const Color(0xFF000000));
|
||||
row.add(new RenderDecoratedBox(
|
||||
decoration: new BoxDecoration(backgroundColor: const Color(0x7FFFCCCC)),
|
||||
child: new RenderParagraph(new StyledTextSpan(style, <TextSpan>[new PlainTextSpan('foo foo foo')]))
|
||||
child: new RenderParagraph(new TextSpan(style: style, text: 'foo foo foo'))
|
||||
));
|
||||
style = new TextStyle(fontSize: 10.0, color: const Color(0xFF000000));
|
||||
row.add(new RenderDecoratedBox(
|
||||
decoration: new BoxDecoration(backgroundColor: const Color(0x7FCCFFCC)),
|
||||
child: new RenderParagraph(new StyledTextSpan(style, <TextSpan>[new PlainTextSpan('foo foo foo')]))
|
||||
child: new RenderParagraph(new TextSpan(style: style, text: 'foo foo foo'))
|
||||
));
|
||||
RenderFlex subrow = new RenderFlex(alignItems: alignItems, textBaseline: TextBaseline.alphabetic);
|
||||
style = new TextStyle(fontSize: 25.0, color: const Color(0xFF000000));
|
||||
subrow.add(new RenderDecoratedBox(
|
||||
decoration: new BoxDecoration(backgroundColor: const Color(0x7FCCCCFF)),
|
||||
child: new RenderParagraph(new StyledTextSpan(style, <TextSpan>[new PlainTextSpan('foo foo foo foo')]))
|
||||
child: new RenderParagraph(new TextSpan(style: style, text: 'foo foo foo foo'))
|
||||
));
|
||||
subrow.add(new RenderSolidColorBox(const Color(0x7FCCFFFF), desiredSize: new Size(30.0, 40.0)));
|
||||
row.add(subrow);
|
||||
@@ -48,7 +48,7 @@ void main() {
|
||||
|
||||
void addJustificationRow(FlexJustifyContent justify) {
|
||||
const TextStyle style = const TextStyle(color: const Color(0xFF000000));
|
||||
RenderParagraph paragraph = new RenderParagraph(new StyledTextSpan(style, <TextSpan>[new PlainTextSpan('$justify')]));
|
||||
RenderParagraph paragraph = new RenderParagraph(new TextSpan(style: style, text: '$justify'));
|
||||
table.add(new RenderPadding(child: paragraph, padding: new EdgeDims.only(top: 20.0)));
|
||||
RenderFlex row = new RenderFlex(direction: FlexDirection.horizontal);
|
||||
row.add(new RenderSolidColorBox(const Color(0xFFFFCCCC), desiredSize: new Size(80.0, 60.0)));
|
||||
|
||||
@@ -16,7 +16,7 @@ void main() {
|
||||
alignment: const FractionalOffset(0.5, 0.5),
|
||||
// We use a RenderParagraph to display the text 'Hello, world.' without
|
||||
// any explicit styling.
|
||||
child: new RenderParagraph(new PlainTextSpan('Hello, world.'))
|
||||
child: new RenderParagraph(new TextSpan(text: 'Hello, world.'))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -97,9 +97,9 @@ class RenderDots extends RenderBox {
|
||||
void main() {
|
||||
// Create some styled text to tell the user to interact with the app.
|
||||
RenderParagraph paragraph = new RenderParagraph(
|
||||
new StyledTextSpan(
|
||||
new TextStyle(color: Colors.black87),
|
||||
<TextSpan>[ new PlainTextSpan("Touch me!") ]
|
||||
new TextSpan(
|
||||
style: new TextStyle(color: Colors.black87),
|
||||
text: "Touch me!"
|
||||
)
|
||||
);
|
||||
// A stack is a render object that layers its children on top of each other.
|
||||
|
||||
@@ -34,9 +34,24 @@ final TextStyle _kUnderline = const TextStyle(
|
||||
|
||||
Widget toStyledText(String name, String text) {
|
||||
TextStyle lineStyle = (name == "Dave") ? _kDaveStyle : _kHalStyle;
|
||||
return new StyledText(
|
||||
return new RichText(
|
||||
key: new Key(text),
|
||||
elements: [lineStyle, [_kBold, [_kUnderline, name], ":"], text]
|
||||
text: new TextSpan(
|
||||
style: lineStyle,
|
||||
children: <TextSpan>[
|
||||
new TextSpan(
|
||||
style: _kBold,
|
||||
children: <TextSpan>[
|
||||
new TextSpan(
|
||||
style: _kUnderline,
|
||||
text: name
|
||||
),
|
||||
new TextSpan(text: ':')
|
||||
]
|
||||
),
|
||||
new TextSpan(text: text)
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -240,9 +240,7 @@ List<TextPainter> _initPainters(List<String> labels) {
|
||||
for (int i = 0; i < painters.length; ++i) {
|
||||
String label = labels[i];
|
||||
TextPainter painter = new TextPainter(
|
||||
new StyledTextSpan(style, [
|
||||
new PlainTextSpan(label)
|
||||
])
|
||||
new TextSpan(style: style, text: label)
|
||||
);
|
||||
painter
|
||||
..maxWidth = double.INFINITY
|
||||
|
||||
@@ -9,92 +9,86 @@ import 'text_editing.dart';
|
||||
import 'text_style.dart';
|
||||
|
||||
/// An immutable span of text.
|
||||
abstract class TextSpan {
|
||||
// This class must be immutable, because we won't notice when it changes.
|
||||
const TextSpan();
|
||||
void build(ui.ParagraphBuilder builder);
|
||||
ui.ParagraphStyle get paragraphStyle => null;
|
||||
String toPlainText(); // for semantics
|
||||
String toString([String prefix = '']); // for debugging
|
||||
}
|
||||
class TextSpan {
|
||||
const TextSpan({
|
||||
this.style,
|
||||
this.text,
|
||||
this.children
|
||||
});
|
||||
|
||||
/// An immutable span of unstyled text.
|
||||
class PlainTextSpan extends TextSpan {
|
||||
const PlainTextSpan(this.text);
|
||||
|
||||
/// The text contained in the span.
|
||||
final String text;
|
||||
|
||||
void build(ui.ParagraphBuilder builder) {
|
||||
assert(text != null);
|
||||
builder.addText(text);
|
||||
}
|
||||
|
||||
bool operator ==(dynamic other) {
|
||||
if (other is! PlainTextSpan)
|
||||
return false;
|
||||
final PlainTextSpan typedOther = other;
|
||||
return text == typedOther.text;
|
||||
}
|
||||
|
||||
int get hashCode => text.hashCode;
|
||||
|
||||
String toPlainText() => text;
|
||||
String toString([String prefix = '']) => '$prefix$runtimeType: "$text"';
|
||||
}
|
||||
|
||||
/// An immutable text span that applies a style to a list of children.
|
||||
class StyledTextSpan extends TextSpan {
|
||||
const StyledTextSpan(this.style, this.children);
|
||||
|
||||
/// The style to apply to the children.
|
||||
/// The style to apply to the text and the children.
|
||||
final TextStyle style;
|
||||
|
||||
/// The children to which the style is applied.
|
||||
/// The text contained in the span.
|
||||
///
|
||||
/// If both text and children are non-null, the text will preceed the
|
||||
/// children.
|
||||
final String text;
|
||||
|
||||
/// Additional spans to include as children.
|
||||
///
|
||||
/// If both text and children are non-null, the text will preceed the
|
||||
/// children.
|
||||
final List<TextSpan> children;
|
||||
|
||||
void build(ui.ParagraphBuilder builder) {
|
||||
assert(style != null);
|
||||
assert(children != null);
|
||||
builder.pushStyle(style.textStyle);
|
||||
for (TextSpan child in children) {
|
||||
assert(child != null);
|
||||
child.build(builder);
|
||||
final bool hasStyle = style != null;
|
||||
if (hasStyle)
|
||||
builder.pushStyle(style.textStyle);
|
||||
if (text != null)
|
||||
builder.addText(text);
|
||||
if (children != null) {
|
||||
for (TextSpan child in children) {
|
||||
assert(child != null);
|
||||
child.build(builder);
|
||||
}
|
||||
}
|
||||
builder.pop();
|
||||
if (hasStyle)
|
||||
builder.pop();
|
||||
}
|
||||
|
||||
ui.ParagraphStyle get paragraphStyle => style.paragraphStyle;
|
||||
void writePlainText(StringBuffer result) {
|
||||
if (text != null)
|
||||
result.write(text);
|
||||
if (children != null) {
|
||||
for (TextSpan child in children)
|
||||
child.writePlainText(result);
|
||||
}
|
||||
}
|
||||
|
||||
String toString([String prefix = '']) {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.writeln('$prefix$runtimeType:');
|
||||
String indent = '$prefix ';
|
||||
buffer.writeln(style.toString(indent));
|
||||
if (text != null)
|
||||
buffer.writeln('$indent"$text"');
|
||||
for (TextSpan child in children)
|
||||
buffer.writeln(child.toString(indent));
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
bool operator ==(dynamic other) {
|
||||
if (identical(this, other))
|
||||
return true;
|
||||
if (other is! StyledTextSpan)
|
||||
if (other is! TextSpan)
|
||||
return false;
|
||||
final StyledTextSpan typedOther = other;
|
||||
if (style != typedOther.style ||
|
||||
children.length != typedOther.children.length)
|
||||
final TextSpan typedOther = other;
|
||||
if (typedOther.text != text)
|
||||
return false;
|
||||
for (int i = 0; i < children.length; ++i) {
|
||||
if (children[i] != typedOther.children[i])
|
||||
return false;
|
||||
if (typedOther.style != style)
|
||||
return false;
|
||||
if ((typedOther.children == null) != (children == null))
|
||||
return false;
|
||||
if (children != null) {
|
||||
for (int i = 0; i < children.length; ++i) {
|
||||
if (typedOther.children[i] != children[i])
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int get hashCode => hashValues(style, hashList(children));
|
||||
|
||||
String toPlainText() => children.map((TextSpan child) => child.toPlainText()).join();
|
||||
|
||||
String toString([String prefix = '']) {
|
||||
List<String> result = <String>[];
|
||||
result.add('$prefix$runtimeType:');
|
||||
var indent = '$prefix ';
|
||||
result.add('${style.toString(indent)}');
|
||||
for (TextSpan child in children)
|
||||
result.add(child.toString(indent));
|
||||
return result.join('\n');
|
||||
}
|
||||
int get hashCode => hashValues(style, text, hashList(children));
|
||||
}
|
||||
|
||||
/// An object that paints a [TextSpan] into a canvas.
|
||||
@@ -115,7 +109,7 @@ class TextPainter {
|
||||
_text = value;
|
||||
ui.ParagraphBuilder builder = new ui.ParagraphBuilder();
|
||||
_text.build(builder);
|
||||
_paragraph = builder.build(_text.paragraphStyle ?? new ui.ParagraphStyle());
|
||||
_paragraph = builder.build(_text.style?.paragraphStyle ?? new ui.ParagraphStyle());
|
||||
_needsLayout = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ final String _kZeroWidthSpace = new String.fromCharCode(0x200B);
|
||||
/// A single line of editable text.
|
||||
class RenderEditableLine extends RenderBox {
|
||||
RenderEditableLine({
|
||||
StyledTextSpan text,
|
||||
TextSpan text,
|
||||
Color cursorColor,
|
||||
bool showCursor: false,
|
||||
Color selectionColor,
|
||||
@@ -49,12 +49,12 @@ class RenderEditableLine extends RenderBox {
|
||||
ValueChanged<TextSelection> onSelectionChanged;
|
||||
|
||||
/// The text to display
|
||||
StyledTextSpan get text => _textPainter.text;
|
||||
TextSpan get text => _textPainter.text;
|
||||
final TextPainter _textPainter;
|
||||
void set text(StyledTextSpan value) {
|
||||
void set text(TextSpan value) {
|
||||
if (_textPainter.text == value)
|
||||
return;
|
||||
StyledTextSpan oldStyledText = _textPainter.text;
|
||||
TextSpan oldStyledText = _textPainter.text;
|
||||
if (oldStyledText.style != value.style)
|
||||
_layoutTemplate = null;
|
||||
_textPainter.text = value;
|
||||
|
||||
@@ -100,7 +100,9 @@ class RenderParagraph extends RenderBox {
|
||||
|
||||
Iterable<SemanticAnnotator> getSemanticAnnotators() sync* {
|
||||
yield (SemanticsNode node) {
|
||||
node.label = text.toPlainText();
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
text.writePlainText(buffer);
|
||||
node.label = buffer.toString();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1405,12 +1405,12 @@ class Flexible extends ParentDataWidget<Flex> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A raw paragraph of text.
|
||||
/// A paragraph of rich text.
|
||||
///
|
||||
/// This class is rarely used directly. Instead, consider using [Text], which
|
||||
/// integrates with [DefaultTextStyle].
|
||||
class RawText extends LeafRenderObjectWidget {
|
||||
RawText({ Key key, this.text }) : super(key: key) {
|
||||
class RichText extends LeafRenderObjectWidget {
|
||||
RichText({ Key key, this.text }) : super(key: key) {
|
||||
assert(text != null);
|
||||
}
|
||||
|
||||
@@ -1418,45 +1418,11 @@ class RawText extends LeafRenderObjectWidget {
|
||||
|
||||
RenderParagraph createRenderObject() => new RenderParagraph(text);
|
||||
|
||||
void updateRenderObject(RenderParagraph renderObject, RawText oldWidget) {
|
||||
void updateRenderObject(RenderParagraph renderObject, RichText oldWidget) {
|
||||
renderObject.text = text;
|
||||
}
|
||||
}
|
||||
|
||||
/// A convience widget for paragraphs of text with heterogeneous style.
|
||||
///
|
||||
/// The elements parameter is a recursive list of lists that matches the
|
||||
/// following grammar:
|
||||
///
|
||||
/// `elements ::= "string" | [<text-style> <elements>*]``
|
||||
///
|
||||
/// Where "string" is text to display and text-style is an instance of
|
||||
/// TextStyle. The text-style applies to all of the elements that follow.
|
||||
class StyledText extends StatelessComponent {
|
||||
StyledText({ this.elements, Key key }) : super(key: key) {
|
||||
assert(_toSpan(elements) != null);
|
||||
}
|
||||
|
||||
/// The recursive list of lists that describes the text and style to paint.
|
||||
final dynamic elements;
|
||||
|
||||
TextSpan _toSpan(dynamic element) {
|
||||
if (element is String)
|
||||
return new PlainTextSpan(element);
|
||||
if (element is Iterable) {
|
||||
dynamic first = element.first;
|
||||
if (first is! TextStyle)
|
||||
throw new ArgumentError("First element of Iterable is a ${first.runtimeType} not a TextStyle");
|
||||
return new StyledTextSpan(first, element.skip(1).map(_toSpan).toList());
|
||||
}
|
||||
throw new ArgumentError("Element is ${element.runtimeType} not a String or an Iterable");
|
||||
}
|
||||
|
||||
Widget build(BuildContext context) {
|
||||
return new RawText(text: _toSpan(elements));
|
||||
}
|
||||
}
|
||||
|
||||
/// The text style to apply to descendant [Text] widgets without explicit style.
|
||||
class DefaultTextStyle extends InheritedWidget {
|
||||
DefaultTextStyle({
|
||||
@@ -1504,17 +1470,20 @@ class Text extends StatelessComponent {
|
||||
/// replace the closest enclosing [DefaultTextStyle].
|
||||
final TextStyle style;
|
||||
|
||||
TextStyle _getEffectiveStyle(BuildContext context) {
|
||||
if (style == null || style.inherit)
|
||||
return DefaultTextStyle.of(context)?.merge(style) ?? style;
|
||||
else
|
||||
return style;
|
||||
}
|
||||
|
||||
Widget build(BuildContext context) {
|
||||
TextSpan text = new PlainTextSpan(data);
|
||||
TextStyle combinedStyle;
|
||||
if (style == null || style.inherit) {
|
||||
combinedStyle = DefaultTextStyle.of(context)?.merge(style) ?? style;
|
||||
} else {
|
||||
combinedStyle = style;
|
||||
}
|
||||
if (combinedStyle != null)
|
||||
text = new StyledTextSpan(combinedStyle, <TextSpan>[text]);
|
||||
return new RawText(text: text);
|
||||
return new RichText(
|
||||
text: new TextSpan(
|
||||
style: _getEffectiveStyle(context),
|
||||
text: data
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
void debugFillDescription(List<String> description) {
|
||||
|
||||
@@ -25,7 +25,7 @@ class _CheckedModeBannerPainter extends CustomPainter {
|
||||
);
|
||||
|
||||
static final TextPainter textPainter = new TextPainter()
|
||||
..text = new StyledTextSpan(kTextStyles, <TextSpan>[new PlainTextSpan('SLOW MODE')])
|
||||
..text = new TextSpan(style: kTextStyles, text: 'SLOW MODE')
|
||||
..maxWidth = kOffset * 2.0
|
||||
..maxHeight = kHeight
|
||||
..layout();
|
||||
|
||||
@@ -112,7 +112,7 @@ class InputValue {
|
||||
return typedOther.text == text
|
||||
&& typedOther.selection == selection
|
||||
&& typedOther.composing == composing;
|
||||
}
|
||||
}
|
||||
|
||||
int get hashCode => hashValues(
|
||||
text.hashCode,
|
||||
@@ -126,7 +126,7 @@ class InputValue {
|
||||
TextRange composing
|
||||
}) {
|
||||
return new InputValue (
|
||||
text: text ?? this.text,
|
||||
text: text ?? this.text,
|
||||
selection: selection ?? this.selection,
|
||||
composing: composing ?? this.composing
|
||||
);
|
||||
@@ -394,24 +394,27 @@ class _EditableLineWidget extends LeafRenderObjectWidget {
|
||||
..paintOffset = paintOffset;
|
||||
}
|
||||
|
||||
StyledTextSpan get _styledTextSpan {
|
||||
TextSpan get _styledTextSpan {
|
||||
if (!hideText && value.composing.isValid) {
|
||||
TextStyle composingStyle = style.merge(
|
||||
const TextStyle(decoration: TextDecoration.underline)
|
||||
);
|
||||
|
||||
return new StyledTextSpan(style, <TextSpan>[
|
||||
new PlainTextSpan(value.composing.textBefore(value.text)),
|
||||
new StyledTextSpan(composingStyle, <TextSpan>[
|
||||
new PlainTextSpan(value.composing.textInside(value.text))
|
||||
]),
|
||||
new PlainTextSpan(value.composing.textAfter(value.text))
|
||||
return new TextSpan(
|
||||
style: style,
|
||||
children: <TextSpan>[
|
||||
new TextSpan(text: value.composing.textBefore(value.text)),
|
||||
new TextSpan(
|
||||
style: composingStyle,
|
||||
text: value.composing.textInside(value.text)
|
||||
),
|
||||
new TextSpan(text: value.composing.textAfter(value.text))
|
||||
]);
|
||||
}
|
||||
|
||||
String text = value.text;
|
||||
if (hideText)
|
||||
text = new String.fromCharCodes(new List<int>.filled(text.length, 0x2022));
|
||||
return new StyledTextSpan(style, <TextSpan>[ new PlainTextSpan(text) ]);
|
||||
return new TextSpan(style: style, text: text);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ class _SemanticsDebuggerEntry {
|
||||
message = message.trim();
|
||||
if (message != '') {
|
||||
textPainter ??= new TextPainter();
|
||||
textPainter.text = new StyledTextSpan(textStyles, <TextSpan>[new PlainTextSpan(message)]);
|
||||
textPainter.text = new TextSpan(style: textStyles, text: message);
|
||||
textPainter.maxWidth = rect.width;
|
||||
textPainter.maxHeight = rect.height;
|
||||
textPainter.layout();
|
||||
|
||||
@@ -15,11 +15,9 @@ class TestBlockPainter extends Painter {
|
||||
void main() {
|
||||
test('block intrinsics', () {
|
||||
RenderParagraph paragraph = new RenderParagraph(
|
||||
new StyledTextSpan(
|
||||
new TextStyle(
|
||||
height: 1.0
|
||||
),
|
||||
<TextSpan>[new PlainTextSpan('Hello World')]
|
||||
new TextSpan(
|
||||
style: new TextStyle(height: 1.0),
|
||||
text: 'Hello World'
|
||||
)
|
||||
);
|
||||
const BoxConstraints unconstrained = const BoxConstraints();
|
||||
|
||||
@@ -15,7 +15,7 @@ void main() {
|
||||
|
||||
root = new RenderPositionedBox(
|
||||
child: new RenderCustomPaint(
|
||||
child: child = text = new RenderParagraph(new PlainTextSpan('Hello World')),
|
||||
child: child = text = new RenderParagraph(new TextSpan(text: 'Hello World')),
|
||||
painter: new TestCallbackPainter(
|
||||
onPaint: () {
|
||||
baseline1 = child.getDistanceToBaseline(TextBaseline.alphabetic);
|
||||
@@ -29,7 +29,7 @@ void main() {
|
||||
root = new RenderPositionedBox(
|
||||
child: new RenderCustomPaint(
|
||||
child: child = new RenderOverflowBox(
|
||||
child: text = new RenderParagraph(new PlainTextSpan('Hello World')),
|
||||
child: text = new RenderParagraph(new TextSpan(text: 'Hello World')),
|
||||
maxHeight: height1 / 2.0,
|
||||
alignment: const FractionalOffset(0.0, 0.0)
|
||||
),
|
||||
|
||||
@@ -35,9 +35,7 @@ class Label extends Node {
|
||||
|
||||
void paint(Canvas canvas) {
|
||||
if (_painter == null) {
|
||||
PlainTextSpan textSpan = new PlainTextSpan(_text);
|
||||
StyledTextSpan styledTextSpan = new StyledTextSpan(_textStyle, <TextSpan>[textSpan]);
|
||||
_painter = new TextPainter(styledTextSpan);
|
||||
_painter = new TextPainter(new TextSpan(style: _textStyle, text: _text));
|
||||
|
||||
_painter.maxWidth = double.INFINITY;
|
||||
_painter.minWidth = 0.0;
|
||||
|
||||
@@ -166,9 +166,9 @@ class ChartPainter {
|
||||
..value = _roundToPlaces(data.startY + stepSize * i, data.roundToPlaces);
|
||||
if (gridline.value < data.startY || gridline.value > data.endY)
|
||||
continue; // TODO(jackson): Align things so this doesn't ever happen
|
||||
TextSpan text = new StyledTextSpan(
|
||||
_textTheme.body1,
|
||||
[new PlainTextSpan("${gridline.value}")]
|
||||
TextSpan text = new TextSpan(
|
||||
style: _textTheme.body1,
|
||||
text: '${gridline.value}'
|
||||
);
|
||||
gridline.labelPainter = new TextPainter(text)
|
||||
..maxWidth = _rect.width
|
||||
@@ -213,9 +213,9 @@ class ChartPainter {
|
||||
..start = _convertPointToRectSpace(new Point(data.startX, data.indicatorLine), markerRect)
|
||||
..end = _convertPointToRectSpace(new Point(data.endX, data.indicatorLine), markerRect);
|
||||
if (data.indicatorText != null) {
|
||||
TextSpan text = new StyledTextSpan(
|
||||
_textTheme.body1,
|
||||
<TextSpan>[new PlainTextSpan("${data.indicatorText}")]
|
||||
TextSpan text = new TextSpan(
|
||||
style: _textTheme.body1,
|
||||
text: '${data.indicatorText}'
|
||||
);
|
||||
_indicator.labelPainter = new TextPainter(text)
|
||||
..maxWidth = markerRect.width
|
||||
|
||||
Reference in New Issue
Block a user