Skip to content

Latest commit

 

History

History
837 lines (665 loc) · 40.6 KB

README.md

File metadata and controls

837 lines (665 loc) · 40.6 KB

Simple-text-styling-Android

Simple-text-styling-Android- A simple framework for text styling in android

The problem

In android its not very simple to manipulate text in a simple EditText without using a special library or some form of richtext xml widget that consumes large amount of space and makes all text editors similar .This app does just that a simple customization text editing method exists that accepts simple parameters of type or size of span and both the start and end of the spanned text.

For the size parameter :
-1 makes text bold
-2 Highlights text provided the color is in integer hicolor
-3 underline
-4 italic
1 decrease text size by amount var
2 decrease text size by amount var
(any size) changes text to that size

After thorough testing and investigation on text behavior in android this method is the end result

    private void Spanning(int size, int ss, int se) {//Styling
            int st = m.getSelectionStart();
            int end = m.getSelectionEnd();
            int ind = -1;
            int oldei = -1;
    
            m.clearComposingText();
            int maindiff = 0;
            int colororig = hicolor;
    
            int colorchang = 0;
            String separation = "0";
    
            SpannableString selection = new SpannableString(m.getText().subSequence(ss, se));//selected part
            SpannableString selectionl = new SpannableString("");
            SpannableString selectionr = new SpannableString("");
            SpannedString newparts = new SpannedString("");
            AbsoluteSizeSpan[] spannedsize = m.getText().getSpans(ss, se, AbsoluteSizeSpan.class);
            StyleSpan[] spannedsize2 = m.getText().getSpans(ss, se, StyleSpan.class);
            BackgroundColorSpan[] spannedsize3 = m.getText().getSpans(ss, se, BackgroundColorSpan.class);
            UnderlineSpan[] spannedsize4 = m.getText().getSpans(ss, se, UnderlineSpan.class);
            //abs size spans selection
            int v = -1;
    
            if (size < 0) {
                for (int xc = 0; size == -2 ? xc < spannedsize3.length : size == -3 ? xc < spannedsize4.length : xc < spannedsize2.length; xc++) {//check removal
                    int sps = m.getText().getSpanStart(size == -2 ? spannedsize3[xc] : size == -3 ? spannedsize4[xc] : spannedsize2[xc]);
                    int spe = m.getText().getSpanEnd(size == -2 ? spannedsize3[xc] : size == -3 ? spannedsize4[xc] : spannedsize2[xc]);//endinf index
                    if (size == -2) {
                        colororig = spannedsize3[xc].getBackgroundColor();
                        if (colororig != hicolor) {
                            colorchang = 1;
                        }
                    } else if (size == -4 || size == -1) {
                        int vcheck = spannedsize2[xc].getStyle();
                        if ((size == -4 && vcheck == Typeface.BOLD || size == -1 && vcheck == Typeface.ITALIC)) {
    
                            if ((ss == sps && se == spe)) {
                                ind = 1;
                            } else
                                ind = -2;// difference exists
    
                        }
                    }
                    if (!(ss == sps && se == spe)) {
                        if (ss < spe && sps < ss && se>spe ) {// left spanned part within selection
                            maindiff = maindiff + (spe - ss);
                        } else if (se < spe && sps < se && ss<sps ) {//right //
                            maindiff = maindiff + (se - sps);
                        } else if(se-ss>spe-sps){
                        maindiff = maindiff + (spe - sps);// in selection
                    }else
                        maindiff = maindiff + (se - ss);// outside selection
                    } else {
                        maindiff = (se - ss);
                        break;
                    }
    
                }
            }
            int sstyle = 0, shigh = 0, sunder = 0;
            int style = 0, high = 0, under = 0, abs = 0;
    
            int totallength = spannedsize.length + spannedsize2.length + spannedsize3.length + spannedsize4.length;
            int actualtotallength = totallength;
    
            for (int sp = 0; sp < totallength; sp++) {//for inside word
                int pst = -1;
                int pend = -1;
                int subvar = -1;
                int si = -1, ei = -1, si1 = -1, ei1 = -1, si2 = -1, ei2 = -1, si3 = -1, ei3 = -1;
                if (spannedsize.length > (sp + (high + style + under))) {
    
                    si = m.getText().getSpanStart(spannedsize[sp + (high + style + under)]);
                    ei = m.getText().getSpanEnd(spannedsize[sp + (high + style + under)]);//endinf index
    
    
                    CurrentSize = spannedsize[sp + (high + style + under)].getSize();
    
    
                    pst = si;
                    pend = ei;
    
    
                }
                if (spannedsize4.length > sunder + (sp + (high + style + abs))) {
    
                    si3 = m.getText().getSpanStart(spannedsize4[sunder + (sp + (high + style + abs))]);
                    ei3 = m.getText().getSpanEnd(spannedsize4[sunder + (sp + (high + style + abs))]);//endinf index
    
                    if (ei3 < pend) {
                        pend = ei3;
                        pst = si3;
                    } else if (ei3 == pend) {
                        subvar = switchspans(size, sstyle, shigh, sunder, sp, high, under, abs, style);//for getting the right index of the span
    
                        totallength = totallength - 1;
                    } else if (pend == -1) {
                        pst = si3;
                        pend = ei3;
                    }
                }
    
                if (spannedsize2.length > sstyle + (sp + (high + under + abs))) {
    
    
                    si1 = m.getText().getSpanStart(spannedsize2[sstyle + (sp + (high + under + abs))]);
                    ei1 = m.getText().getSpanEnd(spannedsize2[sstyle + (sp + (high + under + abs))]);//endinf index
                    v = spannedsize2[sstyle + (sp + (high + under + abs))].getStyle();
    
                    if (ei1 < pend) {
                        pend = ei1;
                        pst = si1;
    
                    } else if (ei1 == pend) {
                        subvar = switchspans(size, sstyle, shigh, sunder, sp, high, under, abs, style);
                        totallength = totallength - 1;
    
                    } else if (pend == -1) {
                        pst = si1;
                        pend = ei1;
                    }
                }
                if (spannedsize3.length > shigh + (sp + (style + under + abs))) {
    
    
                    si2 = m.getText().getSpanStart(spannedsize3[shigh + (sp + (style + under + abs))]);
                    ei2 = m.getText().getSpanEnd(spannedsize3[shigh + (sp + (style + under + abs))]);//endinf index
                    colororig = spannedsize3[shigh + (sp + (style + under + abs))].getBackgroundColor();
    
    
                    if (ei2 < pend) {
                        pend = ei2;
                        pst = si2;
                    } else if (ei2 == pend) {
                        subvar = switchspans(size, sstyle, shigh, sunder, sp, high, under, abs, style);
                        totallength = totallength - 1;
                    } else if (pend == -1) {
                        pst = si2;
                        pend = ei2;
                    }
                }
                // for selecting the main index, shifting and  shifting similarities
    
                if (pend == ei) {
                    if (subvar == -1) {
                        subvar = sp + (high + style + under);
                    }
                    abs--;
                }
                if (pend == ei1) {
                    if (pend != ei) {
                        if (subvar == -1) {
                            subvar = (sstyle) + (sp + (high + under + abs));
                        }
                        style--;
                    } else {//if there is a similarity
                        sstyle++;
                    }
                }
                if (pend == ei2) {
                    if (pend != ei && pend != ei1) {
                        if (subvar == -1) {
                            subvar = (shigh) + (sp + (style + under + abs));
                        }
                        high--;
                    } else {
                        shigh++;
                    }
                }
                if (pend == ei3) {
                    if (pend != ei && pend != ei1 && pend != ei2) {
                        if (subvar == -1) {
                            subvar = (sunder) + (sp + (high + style + abs));
                        }
                        under--;
                    } else {
                        sunder++;
                    }
                }
    
                if (pst < ss && ss < pend && pend < se) {
    
    
                    if (ss < ei && si < ss && se > ei) {//abs left
    
    
                        selectionl = new SpannableString(m.getText().subSequence(si, ss));
                        selectionl.removeSpan(spannedsize[subvar]);
                        separation = "l";
                        selectionl.setSpan(new AbsoluteSizeSpan(CurrentSize), 0, selectionl.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    
                        pst = ss;
                        si = pst;
    
                    }
                    if (ss < ei1 && si1 < ss && se > ei1) {//STYLE left
                        if (!separation.contains("l")) {
                            selectionl = new SpannableString(m.getText().subSequence(si1, ss));
                            selectionl.removeSpan(spannedsize2[subvar]);
                        }
                        separation = "l";
                        if (v == Typeface.ITALIC) {//fot itallic
                            selectionl.setSpan(new android.text.style.StyleSpan(Typeface.ITALIC), 0, selectionl.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                        } else if (v == Typeface.BOLD_ITALIC) {
                            selectionl.setSpan(new android.text.style.StyleSpan(Typeface.BOLD_ITALIC), 0, selectionl.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                        } else
                            selectionl.setSpan(new android.text.style.StyleSpan(Typeface.BOLD), 0, selectionl.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    
                        pst = ss;
                        si1 = pst;
                    }
                    if (ss < ei2 && si2 < ss && se > ei2) {// highlight left
    
                        if (!separation.contains("l")) {
                            selectionl = new SpannableString(m.getText().subSequence(si2, ss));
                            selectionl.removeSpan(spannedsize3[subvar]);
                        }
                        separation = "l";
    
                        selectionl.setSpan((new BackgroundColorSpan(colororig)), 0, selectionl.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                        pst = ss;
                        si2 = pst;
                    }
                    if (ss < ei3 && si3 < ss && se > ei3) {// underline left
    
                        if (!separation.contains("l")) {
                            selectionl = new SpannableString(m.getText().subSequence(si3, ss));
                            selectionl.removeSpan(spannedsize4[subvar]);
                        }
                        separation = "l";
    
                        selectionl.setSpan((new UnderlineSpan()), 0, selectionl.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    
                        pst = ss;
                        si3 = pst;
                    }
                } else if (se < pend && pst < se && ss < pst) {
    
                    if (se < ei && si < se && ss < si) {//abs right
                        selectionr = new SpannableString(m.getText().subSequence(si, se));
                        selectionr.removeSpan(spannedsize[subvar]);
                        separation = "r";
                        selectionr.setSpan(new AbsoluteSizeSpan(CurrentSize), 0, selectionr.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    
                        pend = se;
                        ei = pend;
                    }
                    if (se < ei1 && si1 < se && ss < si1) {//STYLE right
                        if (!separation.contains("r")) {
                            selectionr = new SpannableString(m.getText().subSequence(si1, se));
                            selectionr.removeSpan(spannedsize2[subvar]);
                        }
                        separation = "r";
                        if (v == Typeface.ITALIC) {//fot itallic
                            selectionr.setSpan(new android.text.style.StyleSpan(Typeface.ITALIC), 0, selectionr.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                        } else if (v == Typeface.BOLD_ITALIC) {
                            selectionr.setSpan(new android.text.style.StyleSpan(Typeface.BOLD_ITALIC), 0, selectionr.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                        } else
                            selectionr.setSpan(new android.text.style.StyleSpan(Typeface.BOLD), 0, selectionr.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    
                        pend = se;
                        ei1 = pend;
                    }
                    if (se < ei2 && si2 < se && ss < si2) {// highlight right
                        if (!separation.contains("r")) {
                            selectionr = new SpannableString(m.getText().subSequence(si2, se));
                            selectionr.removeSpan(spannedsize3[subvar]);
                        }
                        separation = "r";
    
                        selectionr.setSpan((new BackgroundColorSpan(colororig)), 0, selectionr.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    
                        pend = se;
                        ei2 = pend;
                        Toast.makeText(this, String.valueOf(selectionr), Toast.LENGTH_SHORT).show();
    
                    }
                    if (se < ei3 && si3 < se && ss < si3) {// underline right
    
                        if (!separation.contains("r")) {
                            selectionr = new SpannableString(m.getText().subSequence(si3, se));
                            selectionr.removeSpan(spannedsize4[subvar]);
                        }
                        separation = "r";
    
                        selectionr.setSpan((new UnderlineSpan()), 0, selectionr.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    
                        pend = se;
                        ei3 = pend;
                        Toast.makeText(this, String.valueOf(selectionr), Toast.LENGTH_SHORT).show();
    
                    }
    
                }
                //separation implementation
    
                if (separation.equals("l") && sp == 0 || separation.equals("r")) {
    
                    a = (SpannedString) TextUtils.concat(a.subSequence(0, ss - selectionl.length()), selectionl, a.subSequence(ss, selectionr.toString().isEmpty() ? m.length() : se - selectionr.length()), selectionr, selectionr.toString().isEmpty() ? "" : a.subSequence(se, m.length()));
    
                    m.setText(a);
                    //separated so they can only come in right
    
                }
    
    
                if ((ss > si && se <= ei || ss >= si && se < ei) || (ss > si3 && se <= ei3 || ss >= si3 && se < ei3) || ((ss > si1 && se <= ei1 || ss >= si1 && se < ei1)) || ((ss > si2 && se <= ei2 || ss >= si2 && se < ei2))) {//inword
    
    
                    separation = "w";
    
                    if ((ss > si && se <= ei || ss >= si && se < ei)) {
    
                        selectionl = new SpannableString(m.getText().subSequence(si, ss));
                        selectionl.removeSpan(spannedsize[subvar]);
    
                        if (si != ss) {
    
                            selectionl.setSpan(new AbsoluteSizeSpan(CurrentSize), 0, selectionl.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                        }
                        if (ei != se) {
                            selection.removeSpan(spannedsize[subvar]);
                            selection.setSpan(new AbsoluteSizeSpan(CurrentSize), 0, selection.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);//to be done anyways
                        }
                        a = (SpannedString) TextUtils.concat(m.getText().subSequence(0, si), selectionl, selection, m.getText().subSequence(se, m.length()));
    
                        if (ss > si) {//shifting indexis
                            pst = ss;
                        }
                        if (se < ei) {
                            pend = se;
                            ei = pend;
                        }
    
                    }
                    if ((ss > si1 && se <= ei1 || ss >= si1 && se < ei1)) {//styling
    
    
                        if (selectionl.toString().isEmpty()) {
                            selectionl = new SpannableString(m.getText().subSequence(si1, ss));
                        } else
                            selectionl.removeSpan(spannedsize2[subvar]);
    
                        if (si1 != ss) {
                            if (v == Typeface.ITALIC) {
                                selectionl.setSpan(new android.text.style.StyleSpan(Typeface.ITALIC), 0, selectionl.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                            } else if (v == Typeface.BOLD) {
                                selectionl.setSpan(new android.text.style.StyleSpan(Typeface.BOLD), 0, selectionl.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                            } else
                                selectionl.setSpan(new android.text.style.StyleSpan(Typeface.BOLD_ITALIC), 0, selectionl.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                        }
                        if (ei1 != se) {
                            selection.removeSpan(spannedsize2[subvar]);
                            if (v == Typeface.BOLD) {
    
                                selection.setSpan(new android.text.style.StyleSpan(Typeface.BOLD), 0, selection.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                            }
                            if (v == Typeface.ITALIC) {
    
                                selection.setSpan(new android.text.style.StyleSpan(Typeface.ITALIC), 0, selection.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                            }
                            if (v == Typeface.BOLD_ITALIC) {
    
                                selection.setSpan(new android.text.style.StyleSpan(Typeface.BOLD_ITALIC), 0, selection.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                            }
                        }
                        a = (SpannedString) TextUtils.concat(m.getText().subSequence(0, si1), selectionl, selection, m.getText().subSequence(se, m.length()));
    
                        if (ss > si1) {
                            pst = ss;
                        }
                        if (se < ei1) {
                            pend = se;
                            ei1 = pend;
                        }
    
                    }
                    if ((ss > si2 && se <= ei2 || ss >= si2 && se < ei2)) {//highlight
    
    
                        if (selectionl.toString().isEmpty()) {
                            selectionl = new SpannableString(m.getText().subSequence(si2, ss));
                        } else
                            selectionl.removeSpan(spannedsize3[subvar]);
    
                        if (si2 != ss) {
                            selectionl.setSpan((new BackgroundColorSpan(colororig)), 0, selectionl.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                        }
                        if (ei2 != se) {
                            selection.removeSpan(spannedsize3[subvar]);
                            selection.setSpan((new BackgroundColorSpan(colororig)), 0, selection.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                        }
                        a = (SpannedString) TextUtils.concat(m.getText().subSequence(0, si2), selectionl, selection, m.getText().subSequence(se, m.length()));
    
                        if (ss > si2) {
                            pst = ss;
                        }
                        if (se < ei2) {
                            pend = se;
                            ei2 = pend;
                        }
                    }
                    if ((ss > si3 && se <= ei3 || ss >= si3 && se < ei3)) {//underline
    
    
                        if (selectionl.toString().isEmpty()) {
                            selectionl = new SpannableString(m.getText().subSequence(si3, ss));
                        } else
                            selectionl.removeSpan(spannedsize4[subvar]);
    
                        if (si3 != ss) {
                            selectionl.setSpan((new UnderlineSpan()), 0, selectionl.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                        }
    
                        if (ei3 != se) {
                            selection.removeSpan(spannedsize4[subvar]);
                            selection.setSpan((new UnderlineSpan()), 0, selection.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                        }
                        a = (SpannedString) TextUtils.concat(m.getText().subSequence(0, si3), selectionl, selection, m.getText().subSequence(se, m.length()));
    
                        if (ss > si3) {
                            pst = ss;
                        }
                        if (se < ei3) {
                            pend = se;
                            ei3 = pend;
                        }
                    }
    
    
                    m.setText(a);
    
    
                }
    
                if (separation.equals("r") || separation.equals("w")) {//resettinf for word and right part
                    spannedsize4 = m.getText().getSpans(ss, se, UnderlineSpan.class);//abs size spans selection
                    spannedsize3 = m.getText().getSpans(ss, se, BackgroundColorSpan.class);//abs size spans selection
                    spannedsize2 = m.getText().getSpans(ss, se, StyleSpan.class);//abs size spans selection
                    spannedsize = m.getText().getSpans(ss, se, AbsoluteSizeSpan.class);//abs size spans selection
                    if (separation.equals("r")) {//for addingg +ve or -ve
                        int newtotallength = spannedsize.length + spannedsize2.length + spannedsize3.length + spannedsize4.length;
                        if (actualtotallength != newtotallength) {
                            subvar = subvar - (actualtotallength - newtotallength);
                        }
                    }
                }
                if ((size == 0 || size > 0) && pend == ei || (size == -4 || size == -1) && pend == ei1 || size == -2 && pend == ei2 || size == -3 && pend == ei3) {// if span is same type
    
    
                    m.getText().removeSpan(size == -2 && ((maindiff == (se - ss) || colorchang == 1)) ? spannedsize3[subvar] : size == -2 ? null : size == -3 && maindiff == (se - ss) ? spannedsize4[subvar] : size < 0 && (maindiff == (se - ss) || ind == -2) ? spannedsize2[subvar] : size < 0 ? null : spannedsize[subvar]);//for all possabilities plus inf whole span is selected for style spans it gets removed
    
    
                }
    
                if (oldei >= 0 && pst - oldei > 1) {//get middle//
                    if (size == 0) {// FOR middle empty
                        CurrentSize = (int) (m.getTextSize() + var);// input size
                    }
                    selection = new SpannableString(m.getText().subSequence(oldei + 1, pst));
                    selection = empty(size, selection);
                    newparts = (SpannedString) TextUtils.concat(newparts, selection);
                }
                oldei = pend - 1;
    
                selection = new SpannableString(m.getText().subSequence(pst, pend));
    
                if ((ind > -1 || (size == -3 ? pend != ei3 : size == -2 ? pend != ei2 : size < 0 && pend != ei1))) {//if no spans in same type
    
    
                    if (ind > -1) {
                        selection.removeSpan(spannedsize2[subvar]);//remove the prev abs size span
                        m.getText().removeSpan(spannedsize2[subvar]);
                        selection.setSpan(new android.text.style.StyleSpan(Typeface.BOLD_ITALIC), 0, selection.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                    } else if (size == -1) {
    
                        selection.setSpan(new android.text.style.StyleSpan(Typeface.BOLD), 0, selection.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    
    
                    } else if (size == -4) {
    
    
                        selection.setSpan(new android.text.style.StyleSpan(Typeface.ITALIC), 0, selection.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                    } else if (size == -3) {//underlinspan
                        selection.setSpan((new UnderlineSpan()), 0, selection.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                    } else if (size == -2) {//underlinspan
                        selection.setSpan((new BackgroundColorSpan(hicolor)), 0, selection.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                    }
    
    
                } else if ((size == -4 || size == -1) && (ind == -2 || maindiff == (se - ss) && spannedsize2[subvar].getStyle() == Typeface.BOLD_ITALIC)) {
                    if (size == -1 && spannedsize2[subvar].getStyle() == Typeface.BOLD_ITALIC) {//bold
                        if (ind == -2) {
    
                            selection.setSpan(new android.text.style.StyleSpan(Typeface.BOLD_ITALIC), 0, selection.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                        } else
                            selection.setSpan(new android.text.style.StyleSpan(Typeface.ITALIC), 0, selection.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                    } else if (size == -4 && spannedsize2[subvar].getStyle() == Typeface.BOLD_ITALIC) {//bold
                        if (ind == -2) {
                            selection.setSpan(new android.text.style.StyleSpan(Typeface.BOLD_ITALIC), 0, selection.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                        } else
                            selection.setSpan(new android.text.style.StyleSpan(Typeface.BOLD), 0, selection.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                    } else if ((size == -1 && spannedsize2[subvar].getStyle() == Typeface.ITALIC) || (size == -4 && spannedsize2[subvar].getStyle() == Typeface.BOLD)) {//bold
    
                        selection.setSpan(new android.text.style.StyleSpan(Typeface.BOLD_ITALIC), 0, selection.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                    } else if ((size == -1 && spannedsize2[subvar].getStyle() == Typeface.BOLD && ind == -2)) {
                        selection.setSpan(new android.text.style.StyleSpan(Typeface.BOLD), 0, selection.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                    } else if ((size == -4 && spannedsize2[subvar].getStyle() == Typeface.ITALIC && ind == -2)) {
                        selection.setSpan(new android.text.style.StyleSpan(Typeface.ITALIC), 0, selection.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                    }
                } else if (size == -2 && colorchang == 1) {//SPANS HIGHLIGHT AND NON HIGHLIGHT SPANS
                    selection.setSpan((new BackgroundColorSpan(hicolor)), 0, selection.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                } else if (size == 0 || size > 0) {//SPANS ABS SIZE,TOTAL SIZE AND NO SIZE SPANS
                    switch (size) {
                        case 0:
                            if (pend == ei) {
                                if (spannedsize[subvar].getSize() + var < 0) {
                                    CurrentSize = 1;
                                } else
                                    CurrentSize = spannedsize[subvar].getSize() + var;//adding or sub
                            } else if (m.getTextSize() + var < 0) {
                                CurrentSize = 1;
                            } else
                                CurrentSize = (int) (m.getTextSize() + var);// input size
                            break;
                        default:
                            CurrentSize = size;
    
                            break;
                    }
                    selection.setSpan(new AbsoluteSizeSpan(CurrentSize), 0, selection.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                }
    
                if (size == 0) {// FOR middle empty
                    CurrentSize = (int) (m.getTextSize() + var);// input size
                }
    
    
                newparts = (SpannedString) TextUtils.concat(newparts, selection);
    
    
                if (sp == 0 && pst > 0 && ss < pst) {
                    selection = new SpannableString(m.getText().subSequence(ss, pst));
    
                    selection = empty(size, selection);
                    newparts = (SpannedString) TextUtils.concat(selection, newparts);
                }
                if (sp == totallength - 1 && se > pend) {
    
                    selection = new SpannableString(m.getText().subSequence(pend, se));
                    pend = se;//to catch last char
                    selection = empty(size, selection);
                    newparts = (SpannedString) TextUtils.concat(newparts, selection);
                }
    
    
                a = (SpannedString) TextUtils.concat(m.getText().subSequence(0, ss), newparts, m.getText().subSequence(pend, m.length())
                );
    
    
            }
            if (totallength == 0) {
                if (size == -1) {
    
                    selection.setSpan(new android.text.style.StyleSpan(Typeface.BOLD), 0, selection.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                } else if (size == -4) {
    
                    selection.setSpan(new android.text.style.StyleSpan(Typeface.ITALIC), 0, selection.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                } else if (size == -3) {//underlinspan
                    selection.setSpan((new UnderlineSpan()), 0, selection.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                } else if (size == -2) {
                    selection.setSpan((new BackgroundColorSpan(hicolor)), 0, selection.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                } else {
                    if (size == 0) {
                        if (m.getTextSize() + var < 0) {
                            CurrentSize = 1;
                        } else
                            CurrentSize = (int) (m.getTextSize() + var);
                    } else
                        CurrentSize = size;
    
    
                    selection.setSpan(new AbsoluteSizeSpan(CurrentSize), 0, selection.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                }
    
                a = (SpannedString) TextUtils.concat(m.getText().subSequence(0, ss), selection, m.getText().subSequence(se, m.length()));
            }
    
            m.setText(a);
    
            m.setSelection(st, end);
    
        }

As complicated as it seems its actually extremely fast because it takes all different types of spans
simulatinusly in one loop . It deals with a major problem in spanning text in android and thats when part of a spanned text is spanned the texts original span gets removed.

it also comes with these 2 methods

   private SpannableString empty(int size, SpannableString selection) {//for empty parts
      switch (size) {
          case -1:
              selection.setSpan(new android.text.style.StyleSpan(Typeface.BOLD), 0, selection.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
              break;
          case -3:
              selection.setSpan((new UnderlineSpan()), 0, selection.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
              break;
          case -2:
              selection.setSpan((new BackgroundColorSpan(hicolor)), 0, selection.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
              break;
          case -4:
              selection.setSpan(new android.text.style.StyleSpan(Typeface.ITALIC), 0, selection.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
              break;
          default:
              selection.setSpan(new AbsoluteSizeSpan(CurrentSize), 0, selection.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

      }
      return selection;
  }

  private int switchspans(int size, int sstyle, int shigh, int sunder, int sp, int high, int under, int abs, int style) {

      int subvar;
      switch (size) {
          case -1:
          case -4:
              subvar = (sstyle) + (sp + (high + under + abs));
              break;
          case -3:
              subvar = (sunder) + (sp + (high + style + abs));
              break;
          case -2:
              subvar = (shigh) + (sp + (style + under + abs));
              break;

          default:
              subvar = sp + (high + style + under);
              break;
      }

      return subvar;
  }

Saving and retriving

Now since the spanning method separates all the spans preventing any overlap between them the spans can be extracted in string form ,saved then retrieved and spanned normally .Using the following methods

This method serializes the spans into String form:-

        private void serialization(){
            serial="";
    //initiation
            AbsoluteSizeSpan[] spannedsize = m.getText().getSpans(0, m.length(), AbsoluteSizeSpan.class);
            StyleSpan[] spannedsize2 = m.getText().getSpans(0, m.length(), StyleSpan.class);
            BackgroundColorSpan[] spannedsize3 = m.getText().getSpans(0, m.length(), BackgroundColorSpan.class);
            UnderlineSpan[] spannedsize4 = m.getText().getSpans(0, m.length(), UnderlineSpan.class);
    
            int totallength = spannedsize.length + spannedsize2.length + spannedsize3.length + spannedsize4.length;
    for (int i=0;i<totallength;i++){
        int startspan=-1,endspan=-1,startspan2=-1,endspan2=-1,startspan3=-1,endspan3=-1,startspan4=-1,endspan4=-1;
            if (spannedsize.length>i){
               startspan=m.getText().getSpanStart(spannedsize[i]);
                endspan=m.getText().getSpanEnd(spannedsize[i]);
    
                serial=serial+startspan+" "+endspan+" "+"s"+spannedsize[i].getSize();
    
            }
            if (spannedsize2.length>i) {
                startspan2 = m.getText().getSpanStart(spannedsize2[i]);
                endspan2 = m.getText().getSpanEnd(spannedsize2[i]);
                if (startspan == startspan2 && endspan == endspan2) {
                    switch (spannedsize2[i].getStyle()) {
                        case Typeface.ITALIC:
                            serial = serial +" "+"I";
                            break;
                        case Typeface.BOLD:
                            serial = serial +" "+ "B";
                            break;
                        case Typeface.BOLD_ITALIC:
                            serial = serial +" "+ "BI";
                            break;
                    }
    
                } else {
    
                    switch (spannedsize2[i].getStyle()) {
                        case Typeface.ITALIC:
                            serial = serial + (serial.isEmpty() || serial.charAt(serial.length() - 1) == ',' ? "" : " ,") + startspan2 + " " + endspan2 + " " + "I";
                            break;
                        case Typeface.BOLD:
                            serial = serial + (serial.isEmpty() || serial.charAt(serial.length() - 1) == ',' ? "" : " ,") + startspan2 + " " + endspan2 + " " + "B";
                            break;
                        case Typeface.BOLD_ITALIC:
                            serial = serial + (serial.isEmpty() || serial.charAt(serial.length() - 1) == ',' ? "" : " ,") + startspan2 + " " + endspan2 + " " + "BI";
                            break;
                    }
    
    
                }
                if (startspan > -1) {
                    totallength--;
                }
            }
    
            if (spannedsize3.length>i){
                startspan3=m.getText().getSpanStart(spannedsize3[i]);
                endspan3=m.getText().getSpanEnd(spannedsize3[i]);
                if( startspan3==startspan2&&endspan3==endspan2||startspan3==startspan&&endspan3==endspan){
                    spannedsize3[i].getBackgroundColor();
                    serial=serial+" "+spannedsize3[i].getBackgroundColor();
    
                }else{
                    serial=serial+(serial.isEmpty()||serial.charAt(serial.length()-1)==','?"":" ,")+startspan3+" "+endspan3+" "+spannedsize3[i].getBackgroundColor();
    
                }
                if(startspan>-1||startspan2>-1){
                    totallength--;
                }
            }
        if (spannedsize4.length>i){
            startspan4=m.getText().getSpanStart(spannedsize4[i]);
            endspan4=m.getText().getSpanEnd(spannedsize4[i]);
            if( startspan3==startspan4&&endspan3==endspan4||startspan4==startspan2&&endspan4==endspan2||startspan4==startspan&&endspan4==endspan){
                serial=serial+" "+"U";
    
            }else{
                serial=serial+(serial.isEmpty()||serial.charAt(serial.length()-1)==','?"":" ,")+startspan4+" "+endspan4+" "+"U";
    
            }
    
            if(startspan>-1||startspan2>-1||startspan3>-1){
                totallength--;
            }
        }
    
            serial=serial+" ,";
        }
        }

The method gets called then saving the text and serial string separately (can be added inside onBackPressed() function.

          serialization();
            values.put(Database.Text, m.getText().toString());

            values.put(Database.RICHText, serial);
            if(c.getCount()==0) {
                sql.insert(Database.MTable, null, values);
            }else
                sql.update(Database.MTable, values, null, null);
            Toast.makeText(this, "Saved", Toast.LENGTH_SHORT).show();

And finally Retrieving from SQLite database:-

     if (c.moveToFirst()) {//retrival
                String TEXT = c.getString(c.getColumnIndex(Database.Text));
                String seriald= c.getString(c.getColumnIndex(Database.RICHText));
    
                SpannableString RichText= SpannableString.valueOf(TEXT);
    
                if (!seriald.isEmpty()) {
                    String[] commas = seriald.split(",");
                    for (int i = 0; i < commas.length; i++) {
                        int left = Integer.parseInt(commas[i].substring(0, commas[i].indexOf(" ")));
                        int right = Integer.parseInt(commas[i].substring(commas[i].indexOf(" ") + 1, commas[i].indexOf(" ", commas[i].indexOf(" ") + 1)));
    
    
    //search on types in the commas[i] and span accordingly.
                        if (commas[i].contains("BI")) {
                            RichText.setSpan(new android.text.style.StyleSpan(Typeface.BOLD_ITALIC), left, right, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                        }else{
                        if (commas[i].contains("B")) {
                            RichText.setSpan(new android.text.style.StyleSpan(Typeface.BOLD), left, right, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                        }
                        if (commas[i].contains("I")) {
                            RichText.setSpan(new android.text.style.StyleSpan(Typeface.ITALIC), left, right, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                        }
                        }
                        if (commas[i].contains("U")) {
                            RichText.setSpan((new UnderlineSpan()), left, right, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                        }
                        if (commas[i].contains("-")) {
                            int color = Integer.parseInt(commas[i].substring(commas[i].indexOf("-"), commas[i].indexOf(" ", commas[i].indexOf("-"))));
                            RichText.setSpan((new BackgroundColorSpan(color)), left, right, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                        }
                        if (commas[i].contains("s")) {
                            int Size = Integer.parseInt(commas[i].substring(commas[i].indexOf('s') + 1, commas[i].indexOf(" ", commas[i].indexOf('s') + 1)));
                            RichText.setSpan(new AbsoluteSizeSpan(Size), left, right, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                        }
    
                    }
    
                }
                m.setText(RichText);
    
    
    
            }

This app is called NovelMessages https://play.google.com/store/apps/details?id=com.app.boshra.fragments

it has other great features but simple and efficent text spanning is its main one.