Flutter hide random characters of word - flutter

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

Related

How to specify Japanese encoding for a UILabel?

When I attempt to display a Japanese string in a UILabel on iOS, it gets displayed using Chinese encoding instead of Japanese.
The two encodings are nearly identical, except in a few specific cases. For example, here is how the character 直 (Unicode U+76F4) is rendered in Chinese (top) vs. Japanese (bottom):
(see here for more examples)
The only time Japanese strings render correctly is when the user's system locale is ja-jp (Japan), but I'd like it to render as Japanese for all users.
Is there any way to force the Japanese encoding? Android has TextView.TextLocale, but I don't see anything similar on iOS UILabel
(Same question for Android. I tagged this Swift/Objective-C because, although I'm looking for a Xamarin.iOS solution, the API is almost the same)
You just need to specify language identifier for attributed string, like
let label = UILabel()
let text = NSAttributedString(string: "直", attributes: [
.languageIdentifier: "ja", // << this !!
.font: UIFont.systemFont(ofSize: 64)
])
label.attributedText = text
Tested with Xcode 13.2 / iOS 15.2
I found an extremely hacky solution that seems to work. However, it seems absurd that there's no way to simply set the locale of a label, so if anyone finds something I missed, please post an answer.
The trick relies on the fact that the Hiragino font displays kanji using Japanese encoding rather than Chinese encoding by default. However, the font looks like shit for English text, so I have to search every string in every label for Japanese substrings and manually change the font using NSMutableAttributedString. The font is also completely broken so I had to find another workaround to fix that.
[assembly: ExportRenderer(typeof(Label), typeof(RingotanLabelRenderer))]
namespace MyApp
{
public class MyLabelRenderer : LabelRenderer
{
private readonly UIFont HIRAGINO_FONT = UIFont.FromName("HiraginoSans-W6", 1); // Size gets updated later
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
// BUGFIX: Chinese encoding is shown by default. Switch to Hiragino font, which correctly shows Japanese characters
// Taken from https://stackoverflow.com/a/71045204/238419
if (Control?.Text != null && e.PropertyName == "Text")
{
var kanjiRanges = GetJapaneseRanges(Control.Text).ToList();
if (kanjiRanges.Count > 0)
{
var font = HIRAGINO_FONT.WithSize((nfloat)Element.FontSize);
var attributedString = Control.AttributedText == null
? new NSMutableAttributedString(Control.Text)
: new NSMutableAttributedString(Control.AttributedText);
// Search through string for all instances of Japanese characters and update the font
foreach (var (start, end) in kanjiRanges)
{
int length = end - start + 1;
var range = new NSRange(start, length);
attributedString.AddAttribute(UIStringAttributeKey.Font, font, range);
// Bugfix: Hiragino font is broken (https://stackoverflow.com/a/44397572/238419) so needs to be adjusted upwards
// jesus christ Apple
attributedString.AddAttribute(UIStringAttributeKey.BaselineOffset, (NSNumber)(Element.FontSize/10), range);
}
Control.AttributedText = attributedString;
}
}
}
// Returns all (start,end) ranges in the string which contain only Japanese strings
private IEnumerable<(int,int)> GetJapaneseRanges(string str)
{
for (int i = 0; i < str.Length; i++)
{
if (IsJapanese(str[i]))
{
int start = i;
while (i < str.Length - 1 && KanjiHelper.IsJapanese(str[i]))
{
i++;
}
int end = i;
yield return (start, end);
}
}
}
private static bool IsJapanese(char character)
{
// An approximation. See https://github.com/caguiclajmg/WanaKanaSharp/blob/792f45a27d6e543d1b484d6825a9f22a803027fd/WanaKanaSharp/CharacterConstants.cs#L110-L118
// for a more accurate version
return character >= '\u3000' && character <= '\u9FFF'
|| character >= '\uFF00';
}
}
}

How to replace text with image(is it possible in 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')
)
...

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

Non-breaking space in Flutter string interpolation

From time to time I need a non-breaking space in my Flutter Text widgets, e.g. a "Show more" link or a number with unit like "50 km/h".
The following code works fine but it looks overly complicated:
const int $nbsp = 0x00A0; // from https://pub.dev/packages/charcode
print('Hello${String.fromCharCode($nbsp)}World'); // --> prints "Hello World", does not break
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :/
I'm curious if there is a shorter way to use an integer constant from the charcode package in my interpolated string?
The easy way to do it is using escape combination [\u{00A0}]:
Text('Hello\u{00A0}world');
The best solution I have come up with is creating a String extension method.
// string_extension.dart
const int $nbsp = 0x00A0;
extension StringExtension on String {
String get nonBreaking => replaceAll(' ', String.fromCharCode($nbsp));
}
Usage example:
// import 'string_extension.dart';
Text('Hello World'.nonBreaking)

How to trap a PASTE in a TEXT widget

I have a TEXT entry field. I want to limit the entry to letters or digits. Other characters should be converted to an under-score. The following code does this. However when the user pastes into the field, it bypasses the listener and the raw text is put into the field
private class TextKeyVerifyListener implements VerifyListener
{
#Override
public void verifyText( VerifyEvent event )
{
if (Character.isLetterOrDigit( event.character ))
event.text = "" + Character.toUpperCase( event.character );
else if (!Character.isISOControl( event.keyCode ))
event.text = "_";
}
}
How do I trap the paste action so at least I can re-parse the text field. It seems kind of heavy duty to do this in the modify listener for each keystroke. Any solution should be cross-platform :-)
Trapping for CTRL-V might do this, but the user can also use the pop menu and choose paste.
VerifyEvent has a text field containing all the text to be verified. You should be using this rather than the character field. text is set to the full pasted text.
Ok, for anyone else trying to do this:
if (event.keyCode == 0 || !Character.isISOControl( event.keyCode ))
{
StringBuilder text = new StringBuilder();
char[] chars = event.text.toCharArray();
for (char character : chars)
if (Character.isLetterOrDigit( character ))
text.append( Character.toUpperCase( character ) );
else
text.append( "_" ); //$NON-NLS-1$
event.text = text.toString();
}
It's a little heavy for single keystrokes, but it will convert as I wanted.
Thanks!