Android,setSpan twice? - android

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

Related

How to remove span style from SpannableString

I was trying to remove style from my SpannableString but unfortunately is not working, my aim is to remove the style when I click on the text.
SpannableString content = new SpannableString("Test Text");
content.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), 0, content.length(), 0);
...
onClick Action :
content.removeSpan(new StyleSpan(Typeface.BOLD_ITALIC)) // not working
Two styleSpan you new is not the same object. You can use a non-anonymous object to point it. Change your code like that:
StyleSpan styleSpan = new StyleSpan(Typeface.BOLD_ITALIC);
content.setSpan(styleSpan , 0, content.length(), 0);
onClick Action:
content.removeSpan(styleSpan);
textView.setText(content);// to redraw the TextView
As Zheng Xingjie pointed out you can remove a particular span with removeSpan() but you need to store the span object.
However, I came across a case that I need to remove a group of the same style spans anonymously, and leave other styles, So I did it by iterating on this particular type of spans as follows:
In my case, it was BackgroundColorSpan, but I will use StyleSpan like it had been asked:
Java
SpannableString content = new SpannableString("Test Text");
content.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), 0, content.length(), 0);
StyleSpan[] spans = content.getSpans(0, content.length(), StyleSpan.class);
for (StyleSpan styleSpan: spans) content.removeSpan(styleSpan);
textview.setText(content);
Kotlin
val content = SpannableString("Test Text")
content.setSpan(StyleSpan(Typeface.BOLD_ITALIC), 0, content.length, 0)
val spans = content.getSpans(0, content.length, StyleSpan::class.java)
for (styleSpan in spans) content.removeSpan(styleSpan)
textview.setText(content)

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

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.

combining multi strings and text in android

I'm pretty new to android, Java and sqlite. For my first program I'm creating a program that will take user input and place in predefined text.
Example: "text" string1 "more text" string2 "even more text" etc
My text will be one color and strings will display in another color.
I'm using sqlite to seperate my data and code and this is where I hit a wall. Trying to find help on how I will be able to combine my above text into one row/column in my database table.
Using only one above example i could get this up and running. But there will be 50+ of above example for release making a database a must especially when I want to add more after release.
Most probably you've read up on SpannableStringBuilder, which allows you to add color to the text in your TextView's content. Check out the code below:
SpannableStringBuilder ssb = new SpannableStringBuilder(<your text>);
ForegroundColorSpan fcs = new ForegroundColorSpan(Color.rgb(255, 0, 0));
ssb.setSpan(fcs, 0, ssb.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(ssb);
The code above will work in most cases, however what you want is to have different alternating colors on a single TextView. Then you should do the following:
String text = your_text + text_from_database;
SpannableStringBuilder ssb = new SpannableStringBuilder(text);
ForegroundColorSpan fcs = new ForegroundColorSpan(Color.rgb(255, 0, 0));
ForegroundColorSpan fcs2 = new ForegroundColorSpan(Color.rgb(0, 255 0));
ssb.setSpan(fcs, 0, your_text, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.setSpan(fcs2, your_text.length(), ssb.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(ssb);
The above code will now work, but you'll notice that if you add another text your_another_text and want to use the previous fcs instance for a second time, the previously colored your_text will now lose its formatting (color). This time you'll need to create another ForegroundColorSpan fcs3 to format the third part of the SpannableStringBuilder. The key here is to use a character style in a setSpan method only once. See below:
String testTest = "abcdefgh";
String testTest2 = "ijklmnop";
String testTest3 = "qrstuvwxyz";
SpannableStringBuilder ssb = new SpannableStringBuilder(testTest+testTest2+testTest3);
ForegroundColorSpan fcs = new ForegroundColorSpan(Color.rgb(255, 0, 0));
ForegroundColorSpan fcs2 = new ForegroundColorSpan(Color.rgb(0, 255, 0));
ForegroundColorSpan fcs3 = new ForegroundColorSpan(Color.rgb(255, 0, 0));
ssb.setSpan(fcs, 0, testTest.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
ssb.setSpan(fcs2, testTest.length(), (testTest+testTest2).length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
ssb.setSpan(fcs3, (testTest+testTest2).length(), ssb.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
test.setText(ssb);
This method is good if you know you have a fixed number of String elements in your SpannableStringBuilder. If you have wish to have a TextView of dynamic length and number of elements, you need to do this in a different approach. What worked for me was to convert each string element into a SpannableString, use setSpan, and append it to the TextView. This is useful if you're using a loop to build your TextView.
TextView test = (TextView)findViewById(R.id.test);
String testTest = "abcdefgh";
String testTest2 = "ijklmnop";
String testTest3 = "qrstuvwxyz";
SpannableString ssb = new SpannableString(testTest);
ForegroundColorSpan fcs = new ForegroundColorSpan(Color.rgb(255, 0, 0));
ForegroundColorSpan fcs2 = new ForegroundColorSpan(Color.rgb(0, 255, 0));
ForegroundColorSpan fcs3 = new ForegroundColorSpan(Color.rgb(255, 0, 0));
ssb.setSpan(fcs, 0, ssb.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
test.setText(ssb);
SpannableString ssb2 = new SpannableString(testTest2);
ssb2.setSpan(fcs2, 0, ssb2.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
test.append(ssb2);
SpannableString ssb3 = new SpannableString(testTest3);
ssb3.setSpan(fcs3, 0, ssb3.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
test.append(ssb3);

Categories

Resources