removeSpan(styleSpans[i]) remove the previous style from the styled text

Viewed 307

I am trying to remove the bold text from the selected text but when I hit the button it unbolds all the text which I bolded previously. It seems that removeSpan.styleSpan[i] not taking care of what part of the text I selected instead it removes the bold text from the whole bolded span string.

i want the selected part to be unbold only as shown enter image description here

but after hitting the button for remove span it unbolds the whole line like this enter image description here

here is my code i am using for it under one button

 private void boldText(){
  int selectionStartb = texto.getSelectionStart();
  int selectionEndb = texto.getSelectionEnd();

  if (selectionStartb > selectionEndb) {
      int temp = selectionEndb;
      selectionEndb = selectionStartb;
      selectionStartb = temp;
  }
  if (selectionEndb > selectionStartb) {
      Spannable str = texto.getText();
      boolean BL = false;
      StyleSpan[] styleSpans;
      styleSpans = str.getSpans(selectionStartb, selectionEndb, StyleSpan.class);
      // If the selected text-part already has BOLD style on it, then
      // we need to disable it
      for (int i = 0; i < styleSpans.length; i++) {
          if (styleSpans[i].getStyle() == android.graphics.Typeface.BOLD) {
              str.removeSpan(styleSpans[i]);
              BL = true;
          }
      }
      // Else we set BOLD style on it
      if (!BL) {
          str.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), selectionStartb, selectionEndb,
                  Spannable.SPAN_EXCLUSIVE_INCLUSIVE);

      }
        texto.setSelection(selectionStartb, selectionEndb);
  }

}

2 Answers

You're working with this text:

Spannable str = texto.getText();

And you're searching for spans within the selected range:

styleSpans = str.getSpans(selectionStartb, selectionEndb, StyleSpan.class);

It's important to understand what's happening here. You are not getting all the "spanned text", or even all the StyleSpans, inside the selection; you are getting all the StyleSpans applied to the entire text, as long as at least part of them is applied to the selected range.

In other words, even if you've selected only a portion of the spanned text, the StyleSpan object still represents the entire spanned text.

You will have to modify your code to handle all the different possible scenarios:

  • The selected range has no spans on it -> add a span for the selected range
  • The selected range exactly matches a single span -> remove that span
  • The selected range is entirely spanned, but doesn't cover the whole span -> remove the existing span and re-add a span to the range that was previously spanned but not selected
  • The selected range is only partially spanned, and covers the whole span -> remove the existing span and add a span for the selected range
  • The selected range is only partially spanned, but doesn't cover the whole span -> remove the existing span and add a span for the selected range + the range that was previously spanned but not selected

If the question is still actual

Instead of this line:

str.removeSpan(styleSpans[i]);

Try to use something like these lines:

   StyleSpan styleSpan = styleSpans[i]       
   // Get start and end of current span (not current selection)
   int spanStart = str.getSpanStart(styleSpan);
   int spanEnd = str.getSpanEnd(styleSpan);
   // Remove span which contains current selection (This is your code line)... 
   str.removeSpan(styleSpan); 
   // Check if current selection is not the same as current span object
   if (selStart!= spanStart || selEnd != spanEnd){
      // Create new span object before! current selection
      if (selStart - 1 > spanStart && selStart - 1 >= 0){
         str.setSpan(new StyleSpan(android.graphics.Typeface.BOLD),
            spanStart,
            selStart - 1, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
      }
      // Create new span object after! current selection
      if (spanEnd > selEnd + 1 && selEnd + 1 < str.length()){
         str.setSpan(new StyleSpan(android.graphics.Typeface.BOLD),
            selEnd + 1,
            spanEnd, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
      }
   }
Related