How to replace text with image(is it possible in flutter) - flutter

var replaced = text.replaceAll(regExp, '*');
Instead of the asterisk mark can we replace this with actual image..

Ok. So you have bunch of emojis stored locally. and you have to replace a text with emoji.
I don't have a perfect answer. but how you can achieve a path that i can show.
Using a map. as you are suppose to change the text for an image there must be a pair. so you can define a map for it. a key will be a text and the value will be the path of the emoji. considering your folder as a images and format is png.
Map<String, String> myData = {"like" : "images/like.png", "time":
"images/time.png"};
and so on. Like this you can create a full map of it. if it's limited like 30 -40 records that you will do manually.
Now you can perform operations on that. Suppose you have String value = " I like your shirt!";
so we need to scan the string and then search every word inside tha map and replace if you found it.
the code looks like this
void main() {
//your value that you are going to scan
String str = " I like your shirt";
//Defining the map
Map<String, String> data = {"like" : "images/like.png", "shirt" :
"images/shirt.png", "happy" : "images/happy.png"};
//function that will do the changes and display
void replaceTextWithEmojis(String value, Map<String, String> data){
//splitting the value into the array or list of items so we can iterate easily
List<String> inputvalues = str.split(" ");
//looping through the text
for (int i =0; i<inputvalues.length; i++){
//checking where that text is present in the emojis map or not.
if(data.containsKey(inputvalues[i])){
//this will replace the text with the path for that key
inputvalues[i] = data[inputvalues[i]];
}
} //end of the for loop
print(inputvalues);
}
replaceTextWithEmojis(str, data);
}
This will replace with the desired values. But You want to display a image between the text. That's what something difficult. I don't think you can do it in flutter. Or it will be like you need to identify the position of the replaceable text and then break the string and store it in other variable. append the image at the breakpoint. so at the place where we are replacing with the map you can add a widget(child ImageProvider(inputvalue[i]));
I would suggest you to use unicode for emojis.
you can use the package for unicode emjois : https://pub.dev/packages/emojis
Also they will give you better performance.

/// Replace an emoticon or any string token with an image having a tooltip and Help cursor.
static List<Widget> replaceEmoji(final String text, final String fromToken, final String toImgTooltip, final String toImg) {
Widget _getImage(final String path, final String tooltip) => MouseRegion(
cursor: SystemMouseCursors.help,
child: Tooltip(message: tooltip, child: Image.asset(path)),
);
if (!text.contains(fromToken)) {
return [Text(text)];
}
final result = <Widget>[];
var buffer = text;
var n = -1;
while (true) {
n = buffer.indexOf(fromToken);
if (n != 0) {
result.add(Text(buffer.substring(0, n)));
}
result.add(_getImage(toImg, toImgTooltip));
buffer = buffer.substring(n + fromToken.length);
if (buffer.isEmpty) {
break;
}
}
return result;
}
You use it as follows:
...
Wrap(
children: replaceEmoji('my :) face - :):)', ':)', 'smile', 'assets/images/emoji/smile.png')
)
...

Related

I want to validate "Text" in flutter not (TextFormField or Textfield)

I want to validate "Text" in flutter not (TextFormField or Textfield), I want to check if the text is empty and if the text is empty then I want it to navigate to new page automatically.
So basically there's a Text widget where I am displaying data from Api using get method so what I want is, if the text widgets are empty, I want it to navigate to login page.
You need to store the string content of the concerned Text widget in a variable. Then you need to call a conditional operation on it to move to the new page.
Example:
String check = ""; (check == "") ? Navigator.pushNamed((context), "/desired-routeName") : Text(check),
simply you can check by == "";
for example:
String myText = ""
bool isEmpty(String text) => text == "";
isEmpty(myText); //returns true
//now set some value
myText = "some value"
isEmpty(myText); //returns false
then you can navigate based on condition like:
if (isEmpty(myText))
{ //navigation logic goes here
} else {
}
Method 1.
You can declare a variable and pass it to the Text widget. Put your condition on that variable.
Method 2.
Save your Text Widget into a variable and use the data: String? property to access the text inside Text widget.
final textWidget = const Text("Hello World");
if(textWidget.data?.isEmpty()) {
//...
}
else {
//...
}
You can put the condition in didChangeDipendencies() or initState() if you wanna to navigate to new page without any click event.
If you get data from api, i would recommend you to validate your string data with regular expressions. To check empty strings you can se the follow regex.
RegExp regExp = new RegExp(r"^$",caseSensitive: false, multiLine: false,);
if(regExp.allMatches(yourValue)){
Navigator.push(context,MaterialPageRoute(builder: (context) => const SecondRoute()),);
}

Flutter hide random characters of word

I'm building an app about finding words,
I have a screen shows word and description and i want to hide some characters of word.
like A*rpl**e
is there a easier way than split to characters and pick random letters and replace with star(*)
As #Jonathan Ixcayau mentions, you can use a for loop like so:
import 'dart:math';
String censor(String original) {
String newValue = '';
for (int i=0; i<original.length; i++) {
newValue += Random().nextBool()?original[i]:'*';
}
return newValue;
}
You can also do this using some chained functions:
import 'dart:math';
String censor(String value) =>
original.split('').map((v) => Random().nextBool()?v:'*').join();

Flutter FOR loop inside widget

So essentially what I am trying to achieve is this:
But apparently its not allowed in flutter.
I'm trying to load a LIST of restaurant items and their quantity values using a FOR loop and display them unto the app with a text widget. But with the current logic that I used I need to iterate and update the variable of x and range after displaying each item name along with its quantity from their respective lists. The problem here is I can't use the FOR loop within widgets as you would a normal FOR loop where you can place multiple statements within the FOR loop.
The snippet of code below is the logic I'm trying to achieve. It is similar to the code I'm implementing in flutter. The FOR loop portion is the only portion I'm kind of stuck with.
Still kind of new to Flutter, so any help or guidance would be appreciated. Thank you!
void main()
{
int x =0;
int range =0;
List<String> restaurauntNames = ['Jollibee','Chowking','Mcdonalds'];
List<int> orderNumber = [3,2,1];
List<int> itemQuantity = [1,1,2,3,1,3];
List<String> itemName= ['Jolly Spag','Chicken Joy','Peach Mango Pie','Chao Fan','Lauriat','Big Mac'];
for(String i in restaurauntNames)
{
print(i);
for(int z =0; z!=orderNumber[x];z++)
{
print(itemName[z+range]+'---------------'+ itemQuantity[z+range].toString());
}
range = range + orderNumber[x];
x++;
}
You can't put brace in for loop widget, I've got the same problem for quite some time and one the solution was to map the iterated list.
children: [
...restaurantNames.map((i){
print(i);
for(int z = 0; z != loadedOrder.orderNumber[x];z++){
return Text(loadedOrder.itemNames[z + range] + 'X' +loadedOrder.itemQuantity[z + range].toString());
}
range = range + orderNumber[x];
x++;
}).toList(),
],

Flutter - Replace a subsstring with a Widget

I am building an application with flutter, but I am having a bit of trouble with one of my widgets. I am getting a JSON response from an API endpoint in order to build the comments on posts, but I need to be able to take part of a string and wrap it in a GestureDetector, in order to handle "# mentions".
For example: I have the string hey there #MattChris how are you? I need to be able to wrap the #MattChris in a GestureDetector.
At the moment I parse the incoming string and provide a list with each space-separated word from the actual comment. Like so:
List<Widget> comment = new List();
outer: for (String word in json['content'].toString().split(" ")) {
if (word != null && word.isNotEmpty) {
if (word.startsWith('#')) {
comment.add(GestureDetector(
onTap: goToProfile,
child: Text(word + ' ')
);
} else {
comment.add(Text(word + ' '));
}
}
}
Only issue now is that's a lot of extra elements taking up memory, and a difficulty with ensuring that the text wraps in the way I expect. I've seen the answer here, but I'm not sure how to ensure that text wraps as if it were one string in a Text widget.
I was able to come to a working solution. Reading from the implementation I liked to again, and looking in the comments, I decided to use a recursive function:
List<TextSpan> _mentionParser(String message, Iterable<dynamic> mentions) {
if (message == null || message.isEmpty) // Don't return anything if there is no message.
return [];
for (Map<String, dynamic> mention in mentions) { // Loop through the list of names to replace
if (message.contains("#${mention['username']}")) { // If the message contains the name to replace
List<TextSpan> _children = [];
String preUsernameMessage = message.substring(0, message.indexOf("#${mention['username']}")).trimLeft(); // Get everything before the mention
if (preUsernameMessage != null && preUsernameMessage.isNotEmpty)
_children.add(TextSpan(children: _mentionParser(preUsernameMessage, mentions))); // if it isn't empty, recurse and add to the list
_children.add( // Always add the display name to the list
TextSpan(
text: "${mention['display_name']}".trim(),
style: TextStyle(color: Color(0xff2e6da4)),
recognizer: TapGestureRecognizer()
..onTap = () => {gotoProfile(json['username'])}
)
);
String postUsernameMessage = message.substring(message.indexOf("#${mention['username']}") + "#${mention['username']}".length, message.length).trimRight(); // Get everything after the mention
if (postUsernameMessage != null && postUsernameMessage.isNotEmpty) // If it isn't empty, recurse and add it to the list
_children.add(TextSpan(children: _mentionParser(postUsernameMessage, mentions)));
return _children; // return the constructed list
}
}
return [TextSpan(text: message)]; // If the string didn't contain any of the strings to replace, then just return the message as passed.
}
Then I just call this as the children variable on a TextSpan inside Text.rich. It took some time, but I was able to get the implementation working!
public String method(String str) {
if (str != null && str.length() > 0 && str.charAt(str.length() - 1) == 'x') {
str = str.substring(0, str.length() - 1);
}
return str; // to remove last character
}

Getting bytearray from PdfDictionary

Please refer to this picture below taken from itext url https://itextpdf.com/en/resources/faq/technical-support/itext-5/how-add-alternative-text-image-tagged-pdf. I am trying to get the bytearray of the images in the pdf, while traversing all the branches, looking for structural element marked as /Figure. Goal is to insert a tag (alternate text) to the image as well get the byte array of that specific image to which I am adding the alternate text.
Here is the code
static void manipulate(PdfDictionary element)
{
if (element == null)
return;
var t = element.GetBytes();
if (PdfName.FIGURE.Equals(element.Get(PdfName.S)))
{
element.Put(PdfName.ALT, new PdfString("Figure without ALT"));
var byteaarray = element.GetBytes(); //// Here bytearray is null
}
var kids = element.GetAsArray(PdfName.K);
if (kids == null)
return;
for(int i = 0; i < kids.Size; i++)
{
manipulate(kids.GetAsDict(i));
}
}
The program successfully adds alternate text "Figure without ALT" to all the images. However, the bytes of that figure is null.
Can you please tell what am I doing wrong here?
Thank you.