How to convert list of TextSpans to a single text? - flutter

For example I have a list of TextSpan:
List<TextSpan> listTextSpan = [TextSpan(text: "Hello"), TextSpan(text: "World")];
then:
AutoSizeText.rich(
TextSpan(
children: listTextSpan,
)),
So I want to make the list of TextSpan as a single text, That I'll be able to return
AutoSizeText.rich(
TextSpan(
text: singleText,
)),

You can use the fold method in order to combine every item on a list into a single value, the shape of the fold method looks like this:
var result = list.fold(initial, (previous, current) => result);
So in your case, if you just want to get a string of the text of every TextSpan, you would do it like this:
String singleText = listTextSpan.fold(
'',
(prev, curr) => '$prev ${curr.text!}');
the initial value is an empty string and you take the previous value, which is the current string, and add to it a space and the text of the current TextSpan, also note that this will throw an error if one of your text spans does not have a text property, in order to avoid this, you must replace curr.text! to curr.text ?? 'whatever you want'
If you still have issues understanding how the fold method works, you can check the documentation

Related

Flutter divide a long text with images

i am creating a news App which i the content of the news is more than 2000 words, my problem is, i want to divide the content and put images in between them.
something like this
Note:
Both the images and text are coming from firebase...
i want to able to do irrespective the length of the words
You can use RichText widget for this types of complex UI.
RichText(
text: TextSpan(
children: [
TextSpan( text: "Some Text...", ),
WidgetSpan( child:
Image.network(src),
),
TextSpan( text: "Some Text...", ),
],
),
),
To cut a big sentence you can use the split method and create a list and save it as 2 different strings like
List<String> stringList = verylongSentence.split(" ");
int start = 0;
int end = 20;//get first 20 words
/// sublist of stringList
final joinedWords = stringList.sublist(start, end);
/// join the list with space
String _content1 = joinedWords.join(" ");
String _content2 = stringList.sublist(end).join(" ");

How to format Time in Flutter

I have the following function, where within a ListBody I map List values, I have a time parameter that returns a time. This contains unnecessary digits and I want to format it.
In other normal List situations I use the function
var timeFormat = DateFormat("HH:mm");
String timetest = timeFormat.format(my_data);
How can I implement my above function to format the time in the below RichText, where I enter data into TextSpan from the map, and cannot build it as a var outside and then call it in?
var mappedValues = ListBody(
children: [...mappedList.map((m) => RichText (
text: TextSpan(
children: <TextSpan> [
TextSpan(text: m.time!.toLocal().toString(), style: TextStyle(
fontSize: 18 ,
fontWeight: FontWeight.w400,
color: Color(0xff2F2F2F),
fontFamily: 'DMSans'
)
),
]
)))]);
Thank you
Update
Example of initial output
2022-03-05 23:24:00.000
My function will turn it to
23:24
Then you should be able to create a method within this widget that takes the Datetime (m.time) as input and returns the formatted time, as:
String getFormattedTime(DateTime time) {
var timeFormat = DateFormat("HH:mm");
String timePortion = timeFormat.format(time);
return timePortion;
}
Then inside your widget just call it:
TextSpan(text: getFormattedTime(m.time!))
You could also move this method into a common utility class so you can reuse it throughout your app. Let me know if that’s what you looking for and works for your purposes.
Check out this Gist (make sure to run it through DartPad) that I created that illustrates my point. Another suggestion would be to use ListView in favor or ListBody as it is more robust.
You should get output that looks like this:
Let me know if that's clear.

Printing int value in Text widget flutter

How do we print the int value in Text widget? I tried using '$num' but it just come out as instance of num.
This is what i tried so far
Text(
'$widget.count'+'. ',
style: TextStyle(
fontFamily: 'sansPro',
fontSize: 15,
color: Colors.black,
fontWeight: FontWeight.bold,
),
),
In your specific case you need to wrap the data with {}, So update the code to the following,
Text(
'${widget.count}''. ',
//...
);
And for more details:
To "print" or "render" a num value that is an int or a double in dart you can use the .toString() method on the variable. You can also use "String Interpolation" that is to evaluate a variable or an expression in a String.
For Example to create a Text widget that renders the a variable X:
Text(x.toString());
And using String Interpolation, you can use:
Text("$x");
If the variable needs to be evaluated as a part of an expression, That is if the vailable is part of an Object or you want to apply an operation before evaluating the final value, then the expression needs to be wrapped within {}, the code for that would be
Text("${x * 100}");
Text widget accept only data in a String format so you can get value in a int or double format and while displaying it convert it into String format. Consider a code snippet like a below:
intValueCount.toString()

Colorize only a part of a TextForm text

I was wondering if there was a way to customize a TextFormField with more accuracy. I don't want to change the whole text color, but only part of it. For instance, below is the above mention TextFormField and I want to highlight "には" (ie what is between curly braces) by adding a red color. I would like to avoid creating multiple TextFormFields to do this because it will be a mess to assemble the text afterwards but I don't know if it is possible.
WARNING
I am not looking for the RichText widget since I want to customize a TextFormField Widget or any Widget with an editable text.
This Widget is used in a List so I would like not to use a "preview" widget with my input widget.
AND
I don't need a full RichTextEditor since the User should not be able to modify the color. Only parts between curly braces should automatically be colorised.
Looking forwards to see what kind of solutions you guys could come up with !
I've finally found a gist that match my request. For those who are searching an answer to my question, you seems to have to override EditableText (How to change color of particular text in a text field dynamically?). But, it's only a draft and it is not working correctly as for today. I'll try to follow this path and add my answer on this post.
EDIT:
The only thing you have to change to this answer is the following:
#override
TextSpan buildTextSpan() {
final String text = textEditingValue.text;
int textLength = text.length;
if (widget.annotations != null && textLength > 0) {
var items = getRanges();
var children = <TextSpan>[];
for (var item in items) {
if (item.range.end < textLength) {
children.add(
TextSpan(style: item.style, text: item.range.textInside(text)),
);
} else if (item.range.start <= textLength) {
children.add(
TextSpan(
style: item.style,
text: TextRange(start: item.range.start, end: text.length)
.textInside(text)),
);
}
}
return new TextSpan(style: widget.style, children: children);
}
return new TextSpan(style: widget.style, text: text);
}
}
Explanation:
You simply have to correct the buildTextSpan part. The error was raised when you delete a character because the Range could raise an exception when the range end was not meet.
This might not be exactly what you want, but may be this can help you get started in a way.
Use RichText widget.
var text = new RichText(
text: new TextSpan(
style: new TextStyle(
fontSize: 10.0,
),
children: <TextSpan>[
new TextSpan(text: 'Text1'),
new TextSpan(text: 'Text2', style: new TextStyle(),
],
),
);

Is there an easy way to find particular text built from RichText in a Flutter test?

For example, I may have one RichText in current widget tree, that looks like
RichText(
text: TextSpan(
text: 'Hello ',
style: DefaultTextStyle.of(context).style,
children: <TextSpan>[
TextSpan(text: 'bold', style: TextStyle(fontWeight: FontWeight.bold)),
TextSpan(text: ' world!'),
],
),
)
I try to use find.text('Hello bold world!') but it doesn't work because it's not a Text.
Framework solution
I have recently contributed this feature to the Flutter framework, i.e. to the built-in finders.
find.text()
You can now enable a findRichText parameter, which will then also find standalone RichText widgets:
find.text(
'Hello bold world!',
findRichText: true,
)
Simplest solution is to put a key on the RichText and read it that way.
If that's not a good fit for whatever reason, you can use find.byWidgetPredicate and pass a function that matches RichText widgets whose text.toPlainText() returns the string you want.
Here's the find.byWidgetPredicate call.
find.byWidgetPredicate((widget) => fromRichTextToPlainText(widget) == 'Hello bold world!')
Here's the fromRichTextToPlainText helper function. Pass it the RichText widget, it will return the plain text.
String fromRichTextToPlainText(final Widget widget) {
if (widget is RichText) {
if (widget.text is TextSpan) {
final buffer = StringBuffer();
(widget.text as TextSpan).computeToPlainText(buffer);
return buffer.toString();
}
}
return null;
}
I solved for this by digging into the widget a bit more manually
final richTextWidget = tester.element(richTextFinder).widget as RichText;
print(richTextWidget.text.children);
With the children, I can assert they are generated as expected