How to clear formatting of a Spannable Text, including last character? - android

I am using this code to remove formatting of a spannable text from start till end. The problem is that it is working successfully, but the last character in the text is still bold (or italics/underline).
removeSpan is not working on the last character in the text:
int startSelection = 0;
int endSelection = text.length();
if(startSelection > endSelection) {
startSelection = text.getSelectionEnd();
endSelection = text.getSelectionStart();
}
Spannable str = text.getText();
StyleSpan[] ss = str.getSpans(startSelection, endSelection, StyleSpan.class);
for (int i = 0; i < ss.length; i++) {
if (ss[i].getStyle() == android.graphics.Typeface.BOLD) {
str.removeSpan(ss[i]);
}
if (ss[i].getStyle() == android.graphics.Typeface.ITALIC) {
str.removeSpan(ss[i]);
}
}
UnderlineSpan[] ulSpan = str.getSpans(startSelection, endSelection, UnderlineSpan.class);
for (int i = 0; i < ulSpan.length; i++) {
str.removeSpan(ulSpan[i]);
}
str.removeSpan(ss[1]);
text.setText(str);

If you want remove all spans from text use this:
Spannable str = text.getText();
Object spansToRemove[] = str.getSpans(startSelection, endSelection, Object.class);
for(Object span: spansToRemove){
if(span instanceof CharacterStyle)
spannable.removeSpan(span);
}

There is a very simple solution:
When you set the Spannable object to a TextView you use myTextView.setText(spannable); this adds your custom formatting of you assigned to the spannable.
In order to clear all the spans at once from the TextView use: myTextView.setText(spannable.toString());
Example
Spannable spannable = new SpannableString(myTextView.getText().toString());
spannable.setSpan(new ForegroundColorSpan(Color.RED), 8, 13,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannable.setSpan(new BackgroundColorSpan(Color.YELLOW), 4, 30, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannable.setSpan(new BackgroundColorSpan(Color.BLUE), 10, 20, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannable.setSpan(new UnderlineSpan(), 7, 11, 0);
myTextView.setText(spannable); // add all the spannable format
myTextView.setText(spannable.toString()); // clear all the spannable format

The following works for me (given that "text" is your TextView or EditText):
String str = text.getText().toString();
text.setText(str);

I changed the code a little bit. Have a look. I have removed the if conditions inside the loop. It is working now.
fromSelectionSpan = true;
int startSelection = 0;
int endSelection = text.length();
Spannable str = text.getText();
StyleSpan[] ss = str.getSpans(startSelection, endSelection, StyleSpan.class);
for (int i = 0; i < ss.length; i++) {
str.removeSpan(ss[i]);
}
UnderlineSpan[] ulSpan = str.getSpans(startSelection, endSelection, UnderlineSpan.class);
for (int i = 0; i < ulSpan.length; i++) {
str.removeSpan(ulSpan[i]);
}
text.setText(str);
b.setChecked(false);
i.setChecked(false);
u.setChecked(false);
text.setSelection(endSelection);

Here's a small utility method I created as an extension to TextView, tested in API 29:
fun TextView.removeAttributedProperties (forText: String? = null) {
forText?.let {
// check if the text we're highlighting is empty to abort
if (forText.isEmpty()) {
return
}
// compute the start and end indices from the text
val startIdx = text.indexOf(forText)
val endIdx = startIdx + forText.length
// if the indices are out of bounds, abort as well
if (startIdx < 0 || endIdx > text.length) {
return
}
(text as? SpannedString)?.let { spannedString ->
val spannable = spannedString.toSpannable()
val spansToRemove = spannable.getSpans(startIdx, endIdx, CharacterStyle::class.java)
for (span in spansToRemove) {
spannable.removeSpan(span)
}
// update the text back
text = spannable
}
} ?: run {
// if we have no text, let's remove all attributed properties
text = text.toString()
}
}

Simple, re-initiate your SpannableString.
Hope this will save your time.

Related

android No successful match so far

I'm trying to change the background color of a specific text e.g. this is the text xxxx 0 visible and I want to change background color of 0.
Here is my code
private TextView setTVBenutzername(View view, Question question, int groupPosition) {
String BenutzerName = question.Benutzername;
TextView textView = (TextView) view.findViewById(R.id.txtBenutzername);
textView.setTag(groupPosition);
textView.setOnClickListener(this.onGroupClickListenerAll);
textView.setOnLongClickListener(this.onGroupClickListener);
Integer Bewertungen;
Bewertungen = question.Bewertungen;
if (Bewertungen != null) BenutzerName += " " + Bewertungen + "";
BenutzerName += " " + question.onlineState.getStateString();
textView.setText(BenutzerName);
final Spannable spannable = new SpannableString(textView.getText().toString());
// Setting Foreground color to the entire text to red
spannable.setSpan(new ForegroundColorSpan(Color.RED),
0, textView.getText().toString().length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
// Getting the indices of the number (Bewertungen)
Matcher matcher = Pattern.compile("\\d+").matcher(textView.getText().toString());
matcher.find();
int startIndex = matcher.start();
int endIndex = matcher.end();
if (question.online && question.onlineState.state > MainActivity.OnlineState.invisible.state) {
// Setting Foreground color
spannable.setSpan(new ForegroundColorSpan(context.getResources().getColor(R.color.colorUserOnline)),
startIndex, endIndex,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannable);
textView.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_online, 0);
} else {
// Setting Foreground color
spannable.setSpan(new ForegroundColorSpan(context.getResources().getColor(R.color.colorUser)),
startIndex, endIndex,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannable);
textView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
}
return textView;
}
App crash when I run.
Error is
java.lang.IllegalStateException: No successful match so far
at java.util.regex.Matcher.ensureMatch(Matcher.java:1116)
at java.util.regex.Matcher.start(Matcher.java:1158)
at java.util.regex.Matcher.start(Matcher.java:1130)
at de.com.limto.limto1.Controls.QuestionsAdapter.setTVBenutzername(QuestionsAdapter.java:1645)
at de.com.limto.limto1.Controls.QuestionsAdapter.setGroupView(QuestionsAdapter.java:1203)
at de.com.limto.limto1.Controls.QuestionsAdapter.getGroupView(QuestionsAdapter.java:1156)
at android.widget.ExpandableListConnector.getView(ExpandableListConnector.java:446)
find() method returns a Boolean indicating whether a match has found or not, and without match you cannot get the index, so wrap inside if condition, like below
if(matcher.find()){
int startIndex = matcher.start();
int endIndex = matcher.end();
if (question.online && question.onlineState.state > MainActivity.OnlineState.invisible.state) {
// Setting Foreground color
spannable.setSpan(new ForegroundColorSpan(context.getResources().getColor(R.color.colorUserOnline)),
startIndex, endIndex,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannable);
textView.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_online, 0);
} else {
// Setting Foreground color
spannable.setSpan(new ForegroundColorSpan(context.getResources().getColor(R.color.colorUser)),
startIndex, endIndex,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannable);
textView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
}
}

set background for only a part of TextView

For example, I have a textview (multi line): aaaaaaaaabbbbaaa. I want to set background for only 'bbb' characters. I try to use Spannable but it doesn't work with my background is a image from drawable.
Many thanks.
using BackgroundColorSpan you can do that ,but Chinese doesn`t work in right way .
private void replaceText(TextView text, String str, int color) {
Spannable raw = new SpannableString(text.getText());
BackgroundColorSpan[] spans = raw.getSpans(0,raw.length(),BackgroundColorSpan.class);
for (BackgroundColorSpan span : spans) {
raw.removeSpan(span);
}
int index = TextUtils.indexOf(raw, str);
while (index >= 0) {
raw.setSpan(new BackgroundColorSpan(color), index, index + str.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
index = TextUtils.indexOf(raw, str, index + str.length());
}
text.setText(raw);
}
private fun highlightTextPart(
textView: TextView,
mainString: String,
subString: String
) {
if (mainString.contains(subString)) {
val startIndex = mainString.indexOf(subString)
val endIndex = startIndex + subString.length
val spannableString = SpannableString(mainString)
spannableString.setSpan(
BackgroundColorSpan(Color.parseColor("#ff00ff")),
startIndex,
endIndex,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
textView.text = spannableString
}
}
using
highlightTextPart("text text sell text", textView, "sell");

Toggle edit text Typeface

Hello Everyone I am making an app where the user can italicize spannable text on a button click.
// Captures Contextual Menu Clicks//
public void onContextualMenuItemClicked(MenuItem item) {
int id = item.getItemId();
if (id == R.id.bold) {
// do some stuff
}
if (id == R.id.italic) {
int startSelection = noteContent.getSelectionStart();
int endSelection = noteContent.getSelectionEnd();
Spannable spannable = noteContent.getText();
spannable.setSpan(new StyleSpan(Typeface.ITALIC) , startSelection , endSelection , 0);
StyleSpanRemover spanRemover = new StyleSpanRemover();
spanRemover.RemoveStyle(spannable,startSelection,endSelection,Typeface.ITALIC);
}
this code makes it italic
int startSelection = noteContent.getSelectionStart();
int endSelection = noteContent.getSelectionEnd();
Spannable spannable = noteContent.getText();
spannable.setSpan(new StyleSpan(Typeface.ITALIC) , startSelection , endSelection , 0);
This makes it un-italic
StyleSpanRemover spanRemover = new StyleSpanRemover();
spanRemover.RemoveStyle(spannable,startSelection,endSelection,Typeface.ITALIC
I want the user to click the same button to italicize and un-italicize. What if statment can I use to get what TypeFace the spannable selected words are? That way it knows if to italicize or not
UPDATE: this is what I have now
int startSelection = noteContent.getSelectionStart();
int endSelection = noteContent.getSelectionEnd();
Spannable spannable = noteContent.getText();
StyleSpan[] spans = spannable.getSpans(startSelection, endSelection, StyleSpan.class);
if (spans.length == 0) {
spannable.setSpan(new StyleSpan(Typeface.ITALIC), startSelection, endSelection , 0);
} else {
spannable.setSpan(new StyleSpan(Typeface.NORMAL), startSelection, endSelection , 0);
}
even though the code runs the code
spannable.setSpan(new StyleSpan(Typeface.NORMAL), startSelection, endSelection , 0);
and sets it back to normal. but it wont set spans.length back to zero so I cant italicize it again how to i set spans.length to zero.
You can use getSpans(startSelection, endSelection, StyleSpan.class) to see what spans are present in the selection range. Based on that, you can decide whether (and how) to italicize the text. Note the user might highlight a portion that contains both normal text and italicized text.
EDIT
StyleSpan[] spans = spannable.getSpans(startSelection, endSelection, StyleSpan.class);
if (spans.length == 0) {
// no spans, italicize text here
} else {
// TODO
}

display smiley in textview and edittext in android

hello i am developing chat application in which i want to insert smiley
i have not much idea about it how to integrate and display in it
can u give me suggestion for doing the same ?
ImageGetter imageGetter = new ImageGetter() {
public Drawable getDrawable(String source) {
Drawable d = getResources().getDrawable(
R.drawable.happy);
d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
return d;
}
};
cs = Html.fromHtml(
"<img src='"
+ getResources()
.getDrawable(R.drawable.happy)
+ "'/>", imageGetter, null);
System.out.println("cs is:- " + cs);
edttxtemoji.setText(cs);
i found this code, in this it uses images, is this feasible ?
or there is another solutions ?
please give me better solution for this thanx in advance
Yes there is another way for showing smiley within the TextView or EditText. Build a Spannable text using ImageSpanand then setText the Spannable to TextView or EditText. Here is an post for the same.
To set Smiley in edittext
int value=R.id.ic_launcher;
Drawable Smiley = getResources().getDrawable(value);
Smiley.setBounds(0, 0, 15, 15);
SpannableStringBuilder builder = new SpannableStringBuilder();
String imgValue = "["+value+"]";
builder.append(imgValue);
builder.setSpan(new ImageSpan(Smiley), builder.length()-imgValue.length(), builder.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
edit_text.getText().insert(txt.getSelectionStart(), builder);
now to fetch smiley in listview or textview
textview.setText(addSmileySpans(context,edit_text.getText()));
public CharSequence addSmileySpans(Context context, CharSequence msg) {
SpannableStringBuilder builder = new SpannableStringBuilder(your_recieved_message);
Pattern pattern = Pattern.compile("\\[([^\\[\\]]+)\\]");
if( pattern != null )
{
Matcher matcher = pattern.matcher( your_recieved_message );
int matchesSoFar = 0;
while( matcher.find() )
{
CharSequence cs =matcher.group().subSequence(1, matcher.group().length()-1);
int value = Integer.parseInt(cs.toString());
System.out.println("pattern is::"+matcher.group().subSequence(1, matcher.group().length()-1));
int start = matcher.start() - (matchesSoFar * 2);
int end = matcher.end() - (matchesSoFar * 2);
Drawable Smiley = context.getResources().getDrawable(value);
Smiley.setBounds(0, 0,15,15);
builder.setSpan(new ImageSpan(Smiley), start + 1, end - 1, 0 );
builder.delete(start, start + 1);
builder.delete(end - 2, end -1);
matchesSoFar++;
}
}
return builder;
}
I think it is little bit late.
public void addSmily() {
CharSequence text = myEditText.getText();
int resource = R.drawable.ic_menu_emoticons ;
myEditText.setText(getSpannableText(text,resource));
}
private Spannable getSpannableText(CharSequence text, int smilyToAppend) {
Spannable spannable = Factory.getInstance().newSpannable(text+" ");
ImageSpan smilySpan = new ImageSpan(getApplicationContext(),smilyToAppend);
spannable.setSpan(smilySpan, spannable.length()-1, spannable.length(), 0);
return spannable;
}

Can underline words in TextView text

Is there possibility in android to provide TextView some text in Java code with setText(text) function with basic tags like and to make marked words underlined ?
Yes, you can, use the Html.fromhtml() method:
textView.setText(Html.fromHtml("this is <u>underlined</u> text"));
Define a string as:
<resources>
<string name="your_string">This is an <u>underline</u> text demo for TextView.</string>
</resources>
You can use UnderlineSpan from SpannableString class:
SpannableString content = new SpannableString(<your text>);
content.setSpan(new UnderlineSpan(), 0, content.length(), 0);
Then just use textView.setText(content);
tobeunderlined= <u>some text here which is to be underlined</u>
textView.setText(Html.fromHtml("some string"+tobeunderlined+"somestring"));
Most Easy Way
TextView tv = findViewById(R.id.tv);
tv.setText("some text");
setUnderLineText(tv, "some");
Also support TextView childs like EditText, Button, Checkbox
public void setUnderLineText(TextView tv, String textToUnderLine) {
String tvt = tv.getText().toString();
int ofe = tvt.indexOf(textToUnderLine, 0);
UnderlineSpan underlineSpan = new UnderlineSpan();
SpannableString wordToSpan = new SpannableString(tv.getText());
for (int ofs = 0; ofs < tvt.length() && ofe != -1; ofs = ofe + 1) {
ofe = tvt.indexOf(textToUnderLine, ofs);
if (ofe == -1)
break;
else {
wordToSpan.setSpan(underlineSpan, ofe, ofe + textToUnderLine.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.setText(wordToSpan, TextView.BufferType.SPANNABLE);
}
}
}
If you want
- Clickable underline text?
- Underline multiple parts of TextView?
Then Check This Answer

Categories

Resources