Arabic numbers are getting reversed in android textview with bidirectional text/numbers - java

I've been trying to display arabic text with arabic numbers in text view. But the problem is the numbers in text appear in reverse order.
((TranslationViewHolder)holder).text.setText("وَاِذَا لَقُوا الَّذِيْنَ اٰمَنُوْا قَالُوْ٘ا اٰمَنَّاﵗ وَاِذَا خَلَوْا اِلٰي شَيٰطِيْنِهِمْﶈ قَالُوْ٘ا اِنَّا مَعَكُمْﶈ اِنَّمَا نَحْنُ مُسْتَهْزِءُوْنَ ١٤ ");
Here the string has a number at the end, but this number or any other number gets reversed so number '١٤' become '٤١'.
I have already tried to use Bidi as below
String mixedLanguageText = elements[position].getAr(); // mixed-language text
mixedLanguageText = BidiFormatter.getInstance(new Locale("ar")).unicodeWrap(mixedLanguageText, TextDirectionHeuristics.RTL);
((TranslationViewHolder)holder).text.setText(mixedLanguageText);
((TranslationViewHolder)holder).text.setTypeface(typeface);
But it has no impact on the output.
I have also tried to setup text direction like below
mixedLanguageText = BidiFormatter.getInstance(new Locale("ar")).unicodeWrap(mixedLanguageText, TextDirectionHeuristics.ANYRTL_LTR);

Even though you said you tried BidiFormatter, I had the same problem with mixed language 'Hebrew/English' and this is how I solved it:
// msg = "506, cvv או תעודת שהות שגויים";
if(BidiFormatter.getInstance().isRtlContext()){
Locale rtlLocale = Locale.getDefault(); // RTL locale
msg = BidiFormatter.getInstance(rtlLocale).unicodeWrap(msg, TextDirectionHeuristicsCompat.ANYRTL_LTR);
}
Snackbar.make(mDrawerLayout,msg,length).show();
I hope it helps.

Related

Dealing with long Strings & TextView behavior

I’m developing an android app that gets objects from a server and shows them in a simple list.
I’m trying to figure out how to deal with long object’s titles :
Every title populates a designated multi-line TextView.
If a title is longer than 16 characters, it messes with my desired UI.
There are two scenarios I need to solve -
1). If the title is longer than 16 characters & contains more than one word, I need to split the words into different lines (I tried to .split("") and .trim(), but I don’t want to use another view, just break a line in the same one, and the use in ("") seems unreliable to me).
2). If the title is longer than 16 characters and contains only one long word, I only need to change font size specifically.
Any ideas for a good and reliable solution?
Thanks a lot in advance.
use SpannableString for a single view
For title:
SpannableString titleSpan = new SpannableString("title String");
titleSpan.setSpan(new RelativeSizeSpan(1.3f), 0, titleSpan.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
for Message
SpannableString messageSpan = new SpannableString("Message String");
messageSpan.setSpan(new RelativeSizeSpan(1.0f), 0, messageSpan.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
set in TextView
tvTermsPolicyHeading.setText(TextUtils.concat(titleSpan, messageSpan));
Code like below it will work as you need
String title; //your title
//find length of your title
int length = title.length();
if (length>16){
string[] titles = myString.split("\\s+");
int size = titles.length;
if (size < 2){
yourTextview.setText(title);
// reduce the text size of your textview
}else {
String newTitle= "";
for (int i=0;i<titles.length;i++){
newTitle = titles[i]+"\n"
}
yourTextview.setText(newTitle);
}
}
You can split and then concatenate the words using "\n" if there are more than one words.
In case of long word
You can see this question here
Auto-fit TextView for Android
try this:
if(title.split(" ").size > 1){
String line1 = title.substring(0, 16);
int end = line1.lastIndexOf(" ");
titleTextView.setText(title.substring(0,end) + "\n" +
title.substring(end+1,title.size-1);
}else{
titleTextView.setText(title);
titleTextView.setTextSize(yourTextSize);
}
this code should work perfectly for your case.

Setting the color of multiple characters of TextView in java

I will do my best to explain my problem, sorry if I am not clear. Basically I want to set the color of individual characters of a text, and then display them in Android App Development Kit. The problem I am having is that I am taking an array of the characters, and don't know how to set the color of them to a certain hexadecimal value.
For instance if the String is "hello". I would want each character to be a different color.
So I would take 'h' and assign it the hexadecimal value of "#000000". And then display it using xml. Is this possible? Here is what I am attempting to do now with my code.
String end = "";
for (int p = 0; p < charzart.size(); p++) {
if (charzart.get(p).equals(" ")) {
}
else{
Spannable colorSpan = new SpannableString(charzart.get(p));
int fake = Integer.parseInt(color.get(p));
colorSpan.setSpan(new ForegroundColorSpan(fake), 0, 1, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
end += colorSpan;
}
}
output.setText(end);
Right now my code doesn't work and I am not sure why. So i am running through charzart which holds my characters. And then attempting to assign the hexadecimal value ( which I have in another array list called color). I check to see if there is a space, if there is I ignore it and move on until i reach a character. From there, I get the character, set it to a spannable. I then get the color, apply it to the spannable, add it to a string and at the end set the TextView to that string.
Basically I want to know how to assign a hexadecimal value to a character, which will then be outputted by XML.

how to replace a word with in contains() Method form a JtextPane

Well, I'm trying to replace a word by using contains() Method:
String z = tfB.getText().toString();
String show = textPane.getText().toString();
if(show.contains(z)){
// how I specify the word that were found and change it without
effecting anything with in that line
}
well what I main by that:
What I'm trying to do is get the value from the user.
then search if it found replace it with something. For example:
String x = "one two three four five";
It should set the textPane to "one two 3 four five"
or
"one two 3-three-3 four five"
could any one please tell me how to do it.
Thank you
What I'm trying to do is get the value from the user. then search if it found replace it with something.
Don't use the contains() method because you will need to search the text twice:
once to see if the text is found in the string
again to replace the text with a new string.
Instead, use the String.indexof(...) method. It will return the index of the text IF it is found in the String.
Then you should replace the text directly in the Document of the text pane, not in the String itself. So the code would be something like:
int length = textPane.getDocument().getLength();
String text = textPane.getDocument().getText(0, length);
String search = "abc...";
int offset = text.indexOf(search);
if (offset != -1)
{
textPane.setSelectionStart(offset);
textPane.setSelectionEnd(offset + search.length();
textPane.replaceSelection("123...");
}
Also, not that you get the text from the Document, not the text pane. This is to make sure the offsets are correct when you replace the text in the Document. Check out Text and New Lines for more information on why this is important.

Create string with emoji unicode flag countries

i need to create a String with a country flag unicode emoji..I did this:
StringBuffer sb = new StringBuffer();
sb.append(StringEscapeUtils.unescapeJava("\\u1F1EB"));
sb.append(StringEscapeUtils.unescapeJava("\\u1F1F7"));
Expecting one country flag but i havent..How can i get a unicode country flag emoji in String with the unicodes characters?
The problem is, that the "\uXXXX" notation is for 4 hexadecimal digits, forming a 16 bit char.
You have Unicode code points above the 16 bit range, both U+F1EB and U+1F1F7. This will be represented with two chars, a so called surrogate pair.
You can either use the codepoints to create a string:
int[] codepoints = {0x1F1EB, 0x1F1F7};
String s = new String(codepoints, 0, codepoints.length);
Or use the surrogate pairs, derivable like this:
System.out.print("\"");
for (char ch : s.toCharArray()) {
System.out.printf("\\u%04X", (int)ch);
}
System.out.println("\"");
Giving
"\uD83C\uDDEB\uD83C\uDDF7"
Response to the comment: How to Decode
"\uD83C\uDDEB" are two surrogate 16 bit chars representing U+1F1EB and "\uD83C\uDDF7" is the surrogate pair for U+1F1F7.
private static final int CP_REGIONAL_INDICATOR = 0x1F1E7; // A-Z flag codes.
/**
* Get the flag codes of two (or one) regional indicator symbols.
* #param s string starting with 1 or 2 regional indicator symbols.
* #return one or two ASCII letters for the flag, or null.
*/
public static String regionalIndicator(String s) {
int cp0 = regionalIndicatorCodePoint(s);
if (cp0 == -1) {
return null;
}
StringBuilder sb = new StringBuilder();
sb.append((char)(cp0 - CP_REGIONAL_INDICATOR + 'A'));
int n0 = Character.charCount(cp0);
int cp1 = regionalIndicatorCodePoint(s.substring(n0));
if (cp1 != -1) {
sb.append((char)(cp1 - CP_REGIONAL_INDICATOR + 'A'));
}
return sb.toString();
}
private static int regionalIndicatorCodePoint(String s) {
if (s.isEmpty()) {
return -1;
}
int cp0 = s.codePointAt(0);
return CP_REGIONAL_INDICATOR > cp0 || cp0 >= CP_REGIONAL_INDICATOR + 26 ? -1 : cp0;
}
System.out.println("Flag: " + regionalIndicator("\uD83C\uDDEB\uD83C\uDDF7"));
Flag: EQ
You should be able to do that simply using toChars from java.lang.Character.
This works for me:
StringBuffer sb = new StringBuffer();
sb.append(Character.toChars(127467));
sb.append(Character.toChars(127479));
System.out.println(sb);
prints 🇫🇷, which the client can chose to display like a french flag, or in other ways.
If you want to use emojis often, it could be good to use a library that would handle that unicode stuff for you: emoji-java
You would just add the maven dependency:
<dependency>
<groupId>com.vdurmont</groupId>
<artifactId>emoji-java</artifactId>
<version>1.0.0</version>
</dependency>
And call the EmojiManager:
Emoji emoji = EmojiManager.getForAlias("fr");
System.out.println("HEY: " + emoji.getUnicode());
The entire list of supported emojis is here.
I suppose you want to achieve something like this
Let me give you 2 example of unicodes for country flags:
for ROMANIA ---> \uD83C\uDDF7\uD83C\uDDF4
for AMERICA ---> \uD83C\uDDFA\uD83C\uDDF8
You can get this and other country flags unicodes from this site Emoji Unicodes
Once you enter the site, you will see a table with a lot of emoji. Select the tab with FLAGS from that table (is easy to find it) then will appear all the country flags. You need to select one flag from the list, any flag you want... but only ONE. After that will appear a text code in the message box...that is not important. Important is that you have to look in the right of the site where will appear flag and country name of your selected flag. CLICK on that, and on the page that will open you need to find the TABLE named Emoji Character Encoding Data. Scroll until the last part of table where sais: C/C++/Java Src .. there you will find the correct unicode flag. Attention, always select the unicode that is long like that, some times if you are not carefull you can select a simple unicode, not long like that. So, keep that in mind.
Indications image 1
Indication image 2
In the end i will post a sample code from an Android app of mine that will work on java the same way.
ArrayList<String> listLanguages = new ArrayList<>();
listLanguages.add("\uD83C\uDDFA\uD83C\uDDF8 " + getString(R.string.English));
listLanguages.add("\uD83C\uDDF7\uD83C\uDDF4 " + getString(R.string.Romanian));
Another simple custom example:
String flagCountryName = "\uD83C\uDDEF\uD83C\uDDF2 Jamaica";
You can use this variable where you need it. This will show you the flag of Jamaica in front of the text.
This is all, if you did not understand something just ask.
Look at Creating Unicode character from its number
Could not get my machine to print the Unicode you have there, but for other values it works.

How to format text string sent via Share menu

I use the following code to get TEXT sent to my app from other apps via Share menu, and display the TEXT in an EditText.
Intent receivedIntent = getIntent();
String receivedAction = receivedIntent.getAction();
String receivedType = receivedIntent.getType();
TextView txtView = (EditText) findViewById(R.id.edWord);
//if(receivedAction.equals(Intent.ACTION_SEND)){
if (Intent.ACTION_SEND.equals(receivedAction) && receivedType != null) {
if(receivedType.startsWith("text/")) {
String receivedText = receivedIntent.getStringExtra(Intent.EXTRA_TEXT).toLowerCase();
if (receivedText != null)
{
txtView.setText(receivedText);
txtView.requestFocus();
ListView myList=(ListView) findViewById(R.id.lstWord);
myList.setFocusableInTouchMode(true);
myList.setSelection(0);
}
else
txtView.setText("");
}
}
Everything works well, i.e., the sent text is displayed in my EditText (namely edWord in the above code). But the problem is the text sent via Share sometimes consists of meaningless elements or derivatives, e.g.: "word, word', word, or looked, books, tomatoes.
Now what I want is to format the text so that it contains only real word or the base form of the word before it is added to EditText.
I've heard about approximate string matching or fuzzy searching but I have no idea how to apply it to my code. I wonder whether you can give me a little help to solve the above problem, at least with formatting/stripping non-word elements.
Thanks in advance.
I think I have found the answer for the first part of my question, i.e., removing non-word elements from a string (starting and/or ending a string). Here is the code with a bit of Regex algorithm that I use:
String receivedText = receivedIntent.getStringExtra(Intent.EXTRA_TEXT);
if (receivedText != null)
{
receivedText = receivedText.toLowerCase();
//Remove all non-word elements starting and/or ending a string
String strippedInput = receivedText.replaceAll("^\\W+|\\W+$", "");
System.out.println("Stripped string: " + strippedInput);
txtView.setText(strippedInput);
txtView.requestFocus();
ListView myList=(ListView) findViewById(R.id.lstWord);
myList.setFocusableInTouchMode(true);
myList.setSelection(0);
}
For the second part of my question, which is about fuzzy searching, I guess it more or less involves re-coding how my app searches for results from its SQLlite database. This is still my un-answered question.

Categories