TextSpan not displaying return text flutter? - flutter

I'm working on flutter app in which I used TextSpan widget for displaying the text. But when I returend the text from method TextSpan not display this text.
RichText(
text: TextSpan(
children: [
TextSpan(text:formatDate(comments[index].createdAt) +
" at " formatTime(comments[index].createdAt),
)
]
)
)
String formatDate(String time) {
var parsedDate = DateTime.parse(time);
final f = new DateFormat('MMM dd, yyyy').format(parsedDate);
String format = f.toString();
return format;
// f.format(new DateTime.fromMillisecondsSinceEpoch(values[index]["start_time"]*1000));
}
String formatTime(String time) {
var parsedDate = DateTime.parse(time);
final f = new DateFormat('hh:mm a').format(parsedDate);
String format = f.toString();
return format;
// f.format(new DateTime.fromMillisecondsSinceEpoch(values[index]["start_time"]*1000));
}
createdAt: "2019-09-30T02:55:46.428Z"

I tried to recreate your case.
Instead of:
TextSpan(text:formatDate(comments[index].createdAt) +
" at " formatTime(comments[index].createdAt),
)
It should be:
TextSpan(text:formatDate(comments[index].createdAt) +
" at " + formatTime(comments[index].createdAt),
)
Also, I don't know what comments[index].createdAt represents, so I tried to directly pass hardcoded test date and time in formatDate and formatTime method calls respectively and provide color property in TextSpan which helped to display the text on screen properly. Updated sample working code below:
body: Center(
child: RichText(
text: TextSpan(
children: [
TextSpan(text:formatDate("2019-09-30") +
" at " + formatTime("2019-09-30"), style: TextStyle(color: Colors.black)),
]
),
),
),
Result:
Hope this helps.

Try this :
RichText(
text: TextSpan(
children: [
TextSpan(text: '${formatDate(DateTime.now().toString())} at ${formatDate(DateTime.now().toString())}')
]
),
),
//Replace DateTime.now() with your data

Related

flutter : How to change the color of a single word in a sentence?

This is My text I want to change color which is in single quotes and last id, This text is dynamic Its coming from API ->
Your query 'THIS IS TESTING SUBJECT TRYING TO EXPLORE HAHA .' has been raised with ticket id: #0606c2a23d9e
I want to make like this
How to make it like this
you can use RichText widget for this purpose in which you can give different styling to different part of the text
RichText(
text: TextSpan(
text: 'Hello ',
style: DefaultTextStyle.of(context).style,
children: const <TextSpan>[
TextSpan(text: 'bold', style: TextStyle(fontWeight: FontWeight.bold)),
TextSpan(text: ' world!'),
],
),
)
Let's assume that we have a pattern with single quotes
Your query 'THIS IS TESTING SUBJECT TRYING TO EXPLORE HAHA .' has been raised with ticket id: #0606c2a23d9e
Let's split your task into subtasks:
First, specify the regex
final regex = RegExp('\'.+\'');
Next, let's try to find our target value with regex (assume that we have it all the time to omit nullability case here)
final target = regex.stringMatch(string)!;
Next, replace the target in the original string with some placeholder
final placeholder = '{#}';
final updatedString = string.replaceAll(regex, placeholder);
Next, split updatedString into tokens
final tokens = updatedString.split(RegExp(' '));
Next, build our TextSpan's by tokens. If the token is a placeholder then we replace it with the target and needed style
final spans = tokens
.map((e) => e == placeholder
? TextSpan(text: target + ' ', style: TextStyle(color: Colors.blue))
: TextSpan(text: e + ' '))
.toList();
And last, collect everything together
Text.rich(TextSpan(children: spans)))
Full code example
class Page extends StatelessWidget {
final String string;
const Page({Key? key, required this.string}) : super(key: key);
#override
Widget build(BuildContext context) {
final regex = RegExp('\'.+\'');
const placeholder = '{#}';
final target = regex.stringMatch(string)!;
final updatedString = string.replaceAll(regex, placeholder);
final tokens = updatedString.split(RegExp(' '));
final spans = tokens
.map((e) => e == placeholder
? TextSpan(text: target + ' ', style: const TextStyle(color: Colors.blue))
: TextSpan(text: e + ' '))
.toList();
return Center(child: Text.rich(TextSpan(children: spans)));
}
}

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 hide password ENTIRELY in flutter [duplicate]

This question already has answers here:
Flutter: obscureText, how to stop showing typed characters
(2 answers)
Closed last year.
I was searching a lot on the internet about how to hide password in TextFormField, the entirely one. Because obscureText doesn't hide all of it, they give a slightly every character you typed
screenshot
Is there any solution for this? Thx in advance
You need it on Android and iOs, right? Because on other platforms seems to be implemented by default like you want it.
In any case, try this:
class ObscuringTextEditingController extends TextEditingController {
ObscuringTextEditingController(String text) : super(text: text);
#override
TextSpan buildTextSpan({required BuildContext context, TextStyle? style, required bool withComposing}) {
var displayValue = '•' * value.text.length;
if (!value.composing.isValid || !withComposing) {
return TextSpan(style: style, text: displayValue);
}
final TextStyle composingStyle = style?.merge(
const TextStyle(decoration: TextDecoration.underline),
) ??
const TextStyle(decoration: TextDecoration.underline);
return TextSpan(
style: style,
children: <TextSpan>[
TextSpan(text: value.composing.textBefore(displayValue)),
TextSpan(
style: composingStyle,
text: value.composing.textInside(displayValue),
),
TextSpan(text: value.composing.textAfter(displayValue)),
],
);
}
}
Updated the original code from here

How to use a TextSpan as a Widget inside VisibilityDetector

I have text in my app that I want to color differently as time goes on. I did this by using RichText widget with a separate text span for each character and a timer that will then update the the state and repaint all of the text spans appropriately. This works so long as the text isn't too long. It starts to break at around 7-10k characters text.
In order to optimize this I decided to use the VisibilityDetector library because text that isn't visible doesn't need to be colored differently. So I chunked the text and put each chunk in its own visibility detector, and when it isn't visible I just set the text using a Text widget. This works, but a single line will get cut off halfway through and start on the next line since they're separate widgets.
What I would like to do is pass the TextSpan as a child of the VisibilityDetector, but this gives the error that TextSpan is not a subtype of the type Widget. Is there any way to do what I want to do?
This is the type of widget tree I would like to have:
String myText = '';
RichText(
text: TextSpan(
children: myText.chunk().mapIndexed((chunkIndex, chunkText) {
return WidgetSpan(
child: VisibilityDetector(
onVisibilityChanged: (info) => _handleVisibilityChanged(),
child: !chunkIsVisible ?
Text(chunkText) :
TextSpan( //This breaks because its not a subtype of Widget
children: chunkText.characters.mapIndexed((charIndex, char) {
return TextSpan(
text: char,
style: _styleTextBasedOnIndex((chunkIndex * ChunkSize) + charIndex)
)
}
)
)
)
}
)
)
I think you can do this to pass the error:
String myText = '';
RichText(
text: TextSpan(
children: myText.chunk().mapIndexed((chunkIndex, chunkText) {
return WidgetSpan(
child: VisibilityDetector(
onVisibilityChanged: (info) => _handleVisibilityChanged(),
child: !chunkIsVisible ?
Text(chunkText) :
RichText(text: TextSpan( // Use another RichText
children: chunkText.characters.mapIndexed((charIndex, char) {
return TextSpan(
text: char,
style: _styleTextBasedOnIndex((chunkIndex * ChunkSize) + charIndex)
)
}
)
)
)
)
}
)
)

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(),
],
),
);