My app should allow users to style inputted or selected text in an Edittext. Some of these styles are Underline, Strike through, Bold and Italic. They are easily added but I don't know how they could be removed and how I could determine if that style has already been added to the selected text.
Code for adding style:
Spannable str = myEditText.getText();
if (!SpannableUtils.isEmpty(str)) {
str.setSpan(new StrikethroughSpan(), startSelection, endSelection,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
I tried using removeSpan but it didn't work.
Also tried using
str.setSpan(new StyleSpan(android.graphics.Typeface.DEFAULT),
startSelection, endSelection,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
but it poses the error : The constructor StyleSpan(Typeface) is undefined.
I think this class solve your problem.
public class StyleSpanRemover {
public void RemoveOne(Spannable spannable,
int startSelection, int endSelection, Class<?> style){
ArrayList<SpanParts> spansParts = getSpanParts(spannable, startSelection, endSelection);
removeOneSpan(spannable, startSelection, endSelection, style);
restoreSpans(spannable, spansParts);
}
public void RemoveStyle(Spannable spannable,
int startSelection, int endSelection, int styleToRemove){
ArrayList<SpanParts> spansParts = getSpanParts(spannable, startSelection, endSelection);
removeStyleSpan(spannable, startSelection, endSelection, styleToRemove);
restoreSpans(spannable, spansParts);
}
public void RemoveAll(Spannable spannable, int startSelection, int endSelection){
ArrayList<SpanParts> spansParts = getSpanParts(spannable, startSelection, endSelection);
removeAllSpans(spannable, startSelection, endSelection);
restoreSpans(spannable, spansParts);
}
protected void restoreSpans(Spannable spannable, ArrayList<SpanParts> spansParts){
for (SpanParts spanParts : spansParts) {
if(spanParts.part1.canAplly())
spannable.setSpan(spanParts.part1.span, spanParts.part1.start,
spanParts.part1.end,spanParts.span_flag);
if(spanParts.part2.canAplly())
spannable.setSpan(spanParts.part2.span, spanParts.part2.start,
spanParts.part2.end, spanParts.span_flag);
}
}
protected void removeAllSpans(Spannable spannable,int startSelection, int endSelection) {
Object spansToRemove[] = spannable.getSpans(startSelection, endSelection, Object.class);
for(Object span: spansToRemove){
if(span instanceof CharacterStyle)
spannable.removeSpan(span);
}
}
protected void removeOneSpan(Spannable spannable,int startSelection, int endSelection,
Class<?> style) {
CharacterStyle spansToRemove[] = spannable.getSpans(startSelection, endSelection, CharacterStyle.class);
for(CharacterStyle span: spansToRemove){
if(span.getUnderlying().getClass() == style )
spannable.removeSpan(span);
}
}
protected void removeStyleSpan(Spannable spannable, int startSelection,
int endSelection, int styleToRemove) {
MetricAffectingSpan spans[] = spannable.getSpans(startSelection, endSelection, MetricAffectingSpan.class);
for(MetricAffectingSpan span: spans){
int stylesApplied = 0;
int stylesToApply;
int spanStart;
int spanEnd;
int spanFlag;
Object spanUnd = span.getUnderlying();
if(spanUnd instanceof StyleSpan){
spanFlag = spannable.getSpanFlags(spanUnd);
stylesApplied = ((StyleSpan) spanUnd).getStyle();
stylesToApply = stylesApplied & ~styleToRemove;
spanStart = spannable.getSpanStart(span);
spanEnd = spannable.getSpanEnd(span);
if(spanEnd >= 0 && spanStart >= 0){
spannable.removeSpan(span);
spannable.setSpan(new StyleSpan(stylesToApply), spanStart, spanEnd,spanFlag);
}
}
}
}
protected ArrayList<SpanParts> getSpanParts(Spannable spannable,
int startSelection,int endSelection){
ArrayList<SpanParts> spansParts = new ArrayList<SpanParts>();
Object spans[] = spannable.getSpans(startSelection, endSelection, Object.class);
for(Object span: spans){
if(span instanceof CharacterStyle){
SpanParts spanParts = new SpanParts();
int spanStart = spannable.getSpanStart(span);
int spanEnd = spannable.getSpanEnd(span);
if(spanStart == startSelection && spanEnd == endSelection) continue;
spanParts.span_flag = spannable.getSpanFlags(span);
spanParts.part1.span = CharacterStyle.wrap((CharacterStyle) span);
spanParts.part1.start = spanStart;
spanParts.part1.end = startSelection;
spanParts.part2.span = CharacterStyle.wrap((CharacterStyle) span);
spanParts.part2.start = endSelection;
spanParts.part2.end = spanEnd;
spansParts.add(spanParts);
}
}
return spansParts;
}
private class SpanParts{
int span_flag;
Part part1;
Part part2;
SpanParts() {
part1 = new Part();
part2 = new Part();
}
}
private class Part{
CharacterStyle span;
int start;
int end;
boolean canAplly() {
return start < end;
}
}
}
How to use:
int startSelection=editText.getSelectionStart();
int endSelection=editText.getSelectionEnd();
Spannable spannable = editText.getText();
StyleSpanRemover spanRemover = new StyleSpanRemover();
// to remove all styles
spanRemover.RemoveAll(spannable,startSelection,endSelection);
//to remove only StrikethroughSpan style use:
spanRemover.RemoveOne(spannable,startSelection,endSelection,StrikethroughSpan.class);
//to remove one StyleSpan use:
spanRemover.RemoveStyle(spannable,startSelection,endSelection,Typeface.BOLD)
android.graphics.TYPEFACE.Default
returns a Typeface
, and the StyleSpan
constructor takes an int
as paramater.
Try using :
android.graphics.Typeface.DEFAULT.getStyle()
instead of:
android.graphics.Typeface.DEFAULT
I think this way below is the simplest but useful. It works for me.
Please try this code:
myEditText.setTypeface(Typeface.DEFAULT);