Android format TextView with multiple styles - android

I have a dictionary database for an offline dictionary and I need to format the definitions.
The dictionary is in Romanian so you won't understand too much from the definition but I will try to explain the format briefly.
definition example: #ABAGERÍE^2# #s. f.# Meseria de abagiu. - #Abager# + #suf.# $-ie.$
From the online version, I could discover some things
# = italic
^ = upperscript
"#" = bold
$ = underline
Is there any way how can I make this possible in android?

You can use the spannable style classes:
final SpannableStringBuilder sb = new SpannableStringBuilder("Hello World 123456");
sb.setSpan(new StyleSpan(Typeface.BOLD), 0, 7, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
sb.setSpan(new StyleSpan(Typeface.ITALIC), 7, 14, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
sb.setSpan(new ForegroundColorSpan(), 0, 4, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
sb.setSpan(new UnderlineSpan(), 0, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
sb.setSpan(new SuperscriptSpan(), 1, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(sb);
Follow the link to get the full list of ParcelableSpan subclasses:
https://developer.android.com/reference/android/text/ParcelableSpan

Related

Android - Using SpannableStringBuilder for per character color change

Heyo, I'm using SpannableStringBuilder to change a word's each character color. This is how I use it :
SpannableStringBuilder specialSpan = new SpannableStringBuilder();
specialSpan.append(context.getResources().getString(R.string.asdf));
specialSpan.setSpan(new ForegroundColorSpan(context.getResources().getColor(R.color.blue)), 0, 0, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
specialSpan.setSpan(new ForegroundColorSpan(context.getResources().getColor(R.color.purple)), 1, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
specialSpan.setSpan(new ForegroundColorSpan(context.getResources().getColor(R.color.orange)), 2, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
specialSpan.setSpan(new ForegroundColorSpan(context.getResources().getColor(R.color.green)), 3, 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
userSpecialText.setText(specialSpan);
The problem is, the TextView's color doesn't change. Am I missing something here?
Update :
I'm using this other Spannable string builder which works for adding Emojis
for (String part :
partofContent){
if (part.contains(":")){
int firstEq = sb.length();
Typeface font = FontCache.getTypeface("emojione-android.ttf", context);
String convertPart = Emojione.shortnameToUnicode(part, true);
sb.append(convertPart + " ");
int lastEq = sb.length();
sb.setSpan(new CustomTypefaceSpan("", font), firstEq, lastEq, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} else {
sb.append(part + " ");
}
}
And to change the color of a detected user Alias
int aliasStart = sb.length();
sb.append("#" + alias + " ");
int aliasEnd = sb.length();
sb.setSpan(new MyClickableSpan("#" + alias + " "), aliasStart, aliasEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
sb.setSpan(new ForegroundColorSpan(context.getResources().getColor(R.color.miBlue)), aliasStart, aliasEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
sb.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), aliasStart, aliasEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
That worked well too, and it uses the same ForegroundColorSpan in setSpan().
Try like This
SpannableStringBuilder specialSpan = new SpannableStringBuilder();
specialSpan.append(context.getResources().getString(R.string.asdf));
specialSpan.setSpan(new ForegroundColorSpan(context.getResources().getColor(R.color.blue)), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
specialSpan.setSpan(new ForegroundColorSpan(context.getResources().getColor(R.color.purple)), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
specialSpan.setSpan(new ForegroundColorSpan(context.getResources().getColor(R.color.orange)), 2, 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
specialSpan.setSpan(new ForegroundColorSpan(context.getResources().getColor(R.color.green)), 3, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
userSpecialText.setText(specialSpan);
You're specifing same for both start and end that means you're specifying a span of length 0, not a span of length 1.

How to substring a spannable?

I know how to take substring a normal string.
But how can I substring a spannable.
Consider following example.
This is my sample sentence.
now when I substring this i want to get the string "mple sente" just like this and with all this formatings.
In another words I want to substring a spannable not a string.
How can I do this?
Spannable is a CharSequence and you should be able to use CharSequence.subSequence(int start, int end) without losing any information about the spannable
Using below code you can get substring from spannable:
SpannableString ss1 = new SpannableString(s);
ss1.setSpan(new RelativeSizeSpan(1.1f), 0, 6, 0); // set size
ss1.setSpan(new ForegroundColorSpan(Color.RED), 0, 6, 0);
SpannableString ss = new SpannableString("Click here to learn more");
ss.setSpan(clickableSpan, 0, 10, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textview.setText(ss);
Hope it helps you.

Android EditText: How to create an empty bullet paragraph by BulletSpan?

I use the same title with this question, because I think my question is very similar to that one, I read and tested the accepted answer very carefully, however the accepted answer doesn't work for me. Let me describe my question:
My code looks like:
EditText myEdit = (EditText) this.findViewById(R.id.myedit);
myEdit.setText("a\nb\n");
Spannable s = myEdit.getText();
s.setSpan(new BulletSpan(30), 0, 1, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
s.setSpan(new BulletSpan(30), 2, 3, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
s.setSpan(new BulletSpan(30), 4, 4, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
myEdit.setText(s);
What I want to see is:
a
b
[I want to see the 3rd bullet here, but it doesn't show up]
I tried Spannable.SPAN_INCLUSIVE_INCLUSIVE, Spannable.SPAN_INCLUSIVE_EXCLUSIVE, Spannable.SPAN_EXCLUSIVE_INCLUSIVE,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE, but none of these flags works for me.
And if I use these codes:
EditText myEdit = (EditText) this.findViewById(R.id.myedit);
myEdit.setText("a\nb\nc");
Spannable s = myEdit.getText();
s.setSpan(new BulletSpan(30), 0, 1, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
s.setSpan(new BulletSpan(30), 2, 3, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
s.setSpan(new BulletSpan(30), 4, 5, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
myEdit.setText(s);
Then I get the expected result:
a
b
c
I am working on a rich text editor, when user clicks bullet icon, I need to show an empty bullet, but now I am not sure what the problem might be, as I want to make a new empty BulletSpan (with only a dot, but no chars after it), but if there are no chars in the span's start and end, the dot doesn't show up.
It is an ugly solution, but I have not found any better - try adding an empty character in the end (something like zero-width space). This is producing the result you'd like (at least visually):
public void setBulletText(EditText myEdit, String text) {
String[] lines = TextUtils.split(text, "\n");
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
String line = null;
for (int index = 0; index < lines.length; ++index) {
line = lines[index];
int length = spannableStringBuilder.length();
spannableStringBuilder.append(line);
if (index != lines.length - 1) {
spannableStringBuilder.append("\n");
} else if (TextUtils.isEmpty(line)) {
spannableStringBuilder.append("\u200B");
}
spannableStringBuilder.setSpan(new BulletSpan(30), length, length + 1,
Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
}
myEdit.setText(spannableStringBuilder);
}
The result is:
Ideally I'd make a custom EditText class which appends this character internally, but removes it when the text is being sent to any other object.
Is this good?
EditText myEdit = (EditText) this.findViewById(R.id.myedit);
myEdit.setText("a\nb\n\n");
Spannable s = myEdit.getText();
s.setSpan(new BulletSpan(30), 0, 1, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
s.setSpan(new BulletSpan(30), 2, 3, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
s.setSpan(new BulletSpan(30), 4, 5, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
myEdit.setText(s);
myEdit.setSelection(s.length()-1);
The result is
I have a simple solution to this, just add a space at the end of the newline
EditText myEdit = (EditText) this.findViewById(R.id.myedit);
myEdit.setText("a\nb\n "); //notice the space after newline
Spannable s = myEdit.getText();
s.setSpan(new BulletSpan(30), 0, 1, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
s.setSpan(new BulletSpan(30), 2, 3, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
s.setSpan(new BulletSpan(30), 4, 4, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
myEdit.setText(s);

Android,setSpan twice?

Say I have a SpannableString that a URLSpan is set for span in it like this:
SpannableString ss = new SpannableString(text);
ss.setSpan(new URLSpan("com://my.app"), 3, 6,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
Then I set another URLSpan for that span.But second URLSpan does not work and first one works.I can not use ss.removeSpan(what); because I do not want to remove all URLSpans.How I can solve this problem?
I use getSpans() in specific span(That I want to reset for it) to get it's span and then I use removeSpan to remove it:
SpannableString ss = new SpannableString(text);
ss.setSpan(new URLSpan("com://my.app"), 3, 6,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
URLSpan[] toRemoveSpans = ss.getSpans(3, 6, URLSpan.class);
ss.removeSpan(toRemoveSpans[0]);
ss.setSpan(new MyURLSpan("com://my.app"), 3, 6,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

How to make multi spannable text?

This is example.
String source = "This is example text";
Spannable out = new SpannedString(source);
StyleSpan boldSpan = new StyleSpan(Typeface.BOLD);
out.setSpan(boldSpan, 1, 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
out.setSpan(boldSpan, 9, 12, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
//someTextView.setText(out);
Expected result: This is example text ("hi" & "xam" are bold)
Actual result:      This is example text (works only last setSpan method and bold is only "xam")
How to make multi spannable text? It's possible?
Maybe problem is in Spannable.SPAN_EXCLUSIVE_EXCLUSIVE flag? Thanks.
I think you need a new StyleSpan for each.
String source = "This is example text";
Spannable out = new SpannedString(source);
StyleSpan boldSpan = new StyleSpan(Typeface.BOLD);
StyleSpan boldSpan2 = new StyleSpan(Typeface.BOLD);
out.setSpan(boldSpan, 1, 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
out.setSpan(boldSpan2, 9, 12, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
Haven't tried it out though.
The reason is that each bold spannable text must be represented by a StyleSpan. The reason for yours is just the same as reassignment of a value.

Categories

Resources