I have used this StyleSpanRemover
to remove style from selected text, but i have a problem.
I want to have a bold
button that toggle bold style of selected text. it means if the selected text (or part of that) is not bold, bold all of them; and if all of selected text is bold, remove bold style from it.
But when i use this code, after one removing bold style on a text and again bolding it, getStyle()
always returns Typeface.NORMAL
Here is the code i have used:
boolean isAllSpansBold = true;
/**
* Bold selected text
*/
Spannable spannable = new SpannableString(mEditTextContent.getText());
StyleSpan[] styleSpans = mEditTextContent.getText().getSpans(
mEditTextContent.getSelectionStart(),
mEditTextContent.getSelectionEnd(),
StyleSpan.class
);
if(styleSpans.length == 0)
{
spannable.setSpan(
new StyleSpan(Typeface.BOLD),
mEditTextContent.getSelectionStart(),
mEditTextContent.getSelectionEnd(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
Log.d("Ramansoft", "styleSpans.length = 0");
}
else
{
for(int i=0; i<styleSpans.length; i++) {
Log.d("Ramansoft", "The style is: " + String.valueOf(styleSpans[i].getStyle()));
if (styleSpans[i].getStyle() != Typeface.BOLD && styleSpans[i].getStyle() != Typeface.BOLD_ITALIC) {
isAllSpansBold = false;
break;
}
}
if(isAllSpansBold)
{
StyleSpanRemover styleSpanRemover = new StyleSpanRemover();
styleSpanRemover.RemoveStyle(
spannable,
mEditTextContent.getSelectionStart(),
mEditTextContent.getSelectionEnd(),
Typeface.BOLD
);
Log.d("Ramansoft", "isAllSpansBold = true");
}
else
{
spannable.setSpan(
new StyleSpan(Typeface.BOLD),
mEditTextContent.getSelectionStart(),
mEditTextContent.getSelectionEnd(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
Log.d("Ramansoft", "isAllSpansBold = false");
}
Mostafa Lavaei
After many tries, i can do that. Here is the solution.
public class SpanStyleHelper
{
protected EditText mEditText;
protected Spannable mSpannable;
protected int mSelectedTextStart;
protected int mSelectedTextEnd;
public SpanStyleHelper(EditText editText)
{
mEditText = editText;
mSpannable = mEditText.getText();
mSelectedTextStart = mEditText.getSelectionStart();
mSelectedTextEnd = mEditText.getSelectionEnd();
}
public Spannable boldSelectedText()
{
Log.d("Ramansoft", "Try to bold selected text..");
StyleSpan[] styleSpans = mEditText.getText().getSpans(
mSelectedTextStart,
mSelectedTextEnd,
StyleSpan.class
);
if(styleSpans.length > 0) {
int lastSpanEnd = 0;
for (StyleSpan styleSpan : styleSpans) {
/**
* Save old style
*/
int oldStyle = styleSpan.getStyle();
/**
* Get start and end of span
*/
int spanStart = mSpannable.getSpanStart(styleSpan);
int spanEnd = mSpannable.getSpanEnd(styleSpan);
/**
* Before bold this span, we check if any unspanned
* text between this span and last span remains. if any
* unspanned text exist, we should bold it
*/
if(spanStart > lastSpanEnd)
{
mSpannable.setSpan(
new StyleSpan(Typeface.BOLD),
lastSpanEnd,
spanStart,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
}
/**
* Update last span end
*/
lastSpanEnd = spanEnd;
/**
* Remove the span
*/
mSpannable.removeSpan(styleSpan);
/**
* Because we just need change selected text,
* if span start is lower than selected text start or
* if span end is higher than selected text end start
* we should restore span for unselected part of span
*/
if (spanStart < mEditText.getSelectionStart()) {
mSpannable.setSpan(
new StyleSpan(oldStyle),
spanStart,
mSelectedTextStart,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
}
if (spanEnd > mEditText.getSelectionEnd()) {
mSpannable.setSpan(
new StyleSpan(oldStyle),
mSelectedTextEnd,
spanEnd,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
}
/**
* We want to add bold style to current style
* so we most detect current style and change
* the style depend on current style
*/
if (oldStyle == Typeface.ITALIC) {
mSpannable.setSpan(
new StyleSpan(Typeface.BOLD_ITALIC),
spanStart,
spanEnd,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
} else {
mSpannable.setSpan(
new StyleSpan(Typeface.BOLD),
spanStart,
spanEnd,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
}
}
/**
* Now we should check if any
* unspanned selected text remains
*/
if(mSelectedTextEnd != lastSpanEnd)
{
mSpannable.setSpan(
new StyleSpan(Typeface.BOLD),
lastSpanEnd,
mSelectedTextEnd,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
}
}
else
{
mSpannable.setSpan(
new StyleSpan(Typeface.BOLD),
mSelectedTextStart,
mSelectedTextEnd,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
}
return mSpannable;
}
public Spannable unBoldSelectedText()
{
Log.d("Ramansoft", "Try to unbold selected text..");
StyleSpan[] styleSpans = mEditText.getText().getSpans(
mSelectedTextStart,
mSelectedTextEnd,
StyleSpan.class
);
for(StyleSpan styleSpan:styleSpans)
{
/**
* Save old style
*/
int oldStyle = styleSpan.getStyle();
/**
* Get start and end of span
*/
int spanStart = mSpannable.getSpanStart(styleSpan);
int spanEnd = mSpannable.getSpanEnd(styleSpan);
/**
* Remove the span
*/
mSpannable.removeSpan(styleSpan);
/**
* Because we just need change selected text,
* if span start is lower than selected text start or
* if span end is higher than selected text end start
* we should restore span for unselected part of span
*/
if(spanStart < mEditText.getSelectionStart())
{
mSpannable.setSpan(
new StyleSpan(oldStyle),
spanStart,
mSelectedTextStart,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
}
if(spanEnd > mEditText.getSelectionEnd())
{
mSpannable.setSpan(
new StyleSpan(oldStyle),
mSelectedTextEnd,
spanEnd,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
}
/**
* Because we just want to remove bold style,
* if the span has another style, we should restore it
*/
if(oldStyle == Typeface.BOLD_ITALIC)
{
mSpannable.setSpan(
new StyleSpan(Typeface.ITALIC),
spanStart,
spanEnd,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
}
}
return mSpannable;
}
public Spannable toggleBoldSelectedText()
{
Log.d("Ramansoft", "Try to toggle bold selected text..");
boolean isAllSpansBold = true;
StyleSpan[] styleSpans = mEditText.getText().getSpans(
mSelectedTextStart,
mSelectedTextEnd,
StyleSpan.class
);
if(styleSpans.length == 0)
{
return boldSelectedText();
}
else
{
for(StyleSpan styleSpan:styleSpans)
{
Log.d("Ramansoft", "styleSpan.getStyle() = " + styleSpan.getStyle());
if (styleSpan.getStyle() != Typeface.BOLD && styleSpan.getStyle() != Typeface.BOLD_ITALIC) {
isAllSpansBold = false;
break;
}
}
Log.d("Ramansoft", "isAllSpansBold = " + isAllSpansBold);
if(isAllSpansBold)
return unBoldSelectedText();
else
return boldSelectedText();
}
}
public Spannable italicSelectedText()
{
Log.d("Ramansoft", "Try to italic selected text..");
StyleSpan[] styleSpans = mEditText.getText().getSpans(
mSelectedTextStart,
mSelectedTextEnd,
StyleSpan.class
);
if(styleSpans.length > 0)
{
int lastSpanEnd = 0;
for (StyleSpan styleSpan : styleSpans) {
/**
* Save old style
*/
int oldStyle = styleSpan.getStyle();
/**
* Get start and end of span
*/
int spanStart = mSpannable.getSpanStart(styleSpan);
int spanEnd = mSpannable.getSpanEnd(styleSpan);
/**
* Before italic this span, we check if any unspanned
* text between this span and last span remains. if any
* unspanned text exist, we should italic it
*/
if(spanStart > lastSpanEnd)
{
mSpannable.setSpan(
new StyleSpan(Typeface.ITALIC),
lastSpanEnd,
spanStart,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
}
/**
* Update last span end
*/
lastSpanEnd = spanEnd;
/**
* Remove the span
*/
mSpannable.removeSpan(styleSpan);
/**
* Because we just need change selected text,
* if span start is lower than selected text start or
* if span end is higher than selected text end start
* we should restore span for unselected part of span
*/
if (spanStart < mEditText.getSelectionStart()) {
mSpannable.setSpan(
new StyleSpan(oldStyle),
spanStart,
mSelectedTextStart,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
}
if (spanEnd > mEditText.getSelectionEnd()) {
mSpannable.setSpan(
new StyleSpan(oldStyle),
mSelectedTextEnd,
spanEnd,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
}
/**
* We want to add bold style to current style
* so we most detect current style and change
* the style depend on current style
*/
if (oldStyle == Typeface.BOLD) {
mSpannable.setSpan(
new StyleSpan(Typeface.BOLD_ITALIC),
spanStart,
spanEnd,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
} else {
mSpannable.setSpan(
new StyleSpan(Typeface.ITALIC),
spanStart,
spanEnd,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
}
}
/**
* Now we should check if any
* unspanned selected text remains
*/
if(mSelectedTextEnd != lastSpanEnd)
{
mSpannable.setSpan(
new StyleSpan(Typeface.ITALIC),
lastSpanEnd,
mSelectedTextEnd,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
}
}
else
{
mSpannable.setSpan(
new StyleSpan(Typeface.ITALIC),
mSelectedTextStart,
mSelectedTextEnd,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
}
return mSpannable;
}
public Spannable unItalicSelectedText()
{
Log.d("Ramansoft", "Try to un-italic selected text..");
StyleSpan[] styleSpans = mEditText.getText().getSpans(
mSelectedTextStart,
mSelectedTextEnd,
StyleSpan.class
);
for(StyleSpan styleSpan:styleSpans)
{
/**
* Save old style
*/
int oldStyle = styleSpan.getStyle();
/**
* Get start and end of span
*/
int spanStart = mSpannable.getSpanStart(styleSpan);
int spanEnd = mSpannable.getSpanEnd(styleSpan);
/**
* Remove the span
*/
mSpannable.removeSpan(styleSpan);
/**
* Because we just need change selected text,
* if span start is lower than selected text start or
* if span end is higher than selected text end start
* we should restore span for unselected part of span
*/
if(spanStart < mEditText.getSelectionStart())
{
mSpannable.setSpan(
new StyleSpan(oldStyle),
spanStart,
mSelectedTextStart,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
}
if(spanEnd > mEditText.getSelectionEnd())
{
mSpannable.setSpan(
new StyleSpan(oldStyle),
mSelectedTextEnd,
spanEnd,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
}
/**
* Because we just want to remove bold style,
* if the span has another style, we should restore it
*/
if(oldStyle == Typeface.BOLD_ITALIC)
{
mSpannable.setSpan(
new StyleSpan(Typeface.BOLD),
spanStart,
spanEnd,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
}
}
return mSpannable;
}
public Spannable toggleItalicSelectedText()
{
Log.d("Ramansoft", "Try to toggle italic selected text..");
boolean isAllSpansItalic = true;
StyleSpan[] styleSpans = mEditText.getText().getSpans(
mSelectedTextStart,
mSelectedTextEnd,
StyleSpan.class
);
if(styleSpans.length == 0)
{
return italicSelectedText();
}
else
{
for(StyleSpan styleSpan:styleSpans)
{
Log.d("Ramansoft", "styleSpan.getStyle() = " + styleSpan.getStyle());
if (styleSpan.getStyle() != Typeface.ITALIC && styleSpan.getStyle() != Typeface.BOLD_ITALIC) {
isAllSpansItalic = false;
break;
}
}
Log.d("Ramansoft", "isAllSpansItalic = " + isAllSpansItalic);
if(isAllSpansItalic)
return unItalicSelectedText();
else
return italicSelectedText();
}
}
}
来源:https://stackoverflow.com/questions/36307409/remove-style-on-spans