Java Code Examples for android.text.Spanned#getSpans()

The following examples show how to use android.text.Spanned#getSpans() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: MarkwonEditorUtils.java    From Markwon with Apache License 2.0 6 votes vote down vote up
@NonNull
public static Map<Class<?>, List<Object>> extractSpans(@NonNull Spanned spanned, @NonNull Collection<Class<?>> types) {

    final Object[] spans = spanned.getSpans(0, spanned.length(), Object.class);
    final Map<Class<?>, List<Object>> map = new HashMap<>(3);

    Class<?> type;

    for (Object span : spans) {
        type = span.getClass();
        if (types.contains(type)) {
            List<Object> list = map.get(type);
            if (list == null) {
                list = new ArrayList<>(3);
                map.put(type, list);
            }
            list.add(span);
        }
    }

    return map;
}
 
Example 2
Source File: SpannableStringUtils.java    From openboard with GNU General Public License v3.0 6 votes vote down vote up
/**
 * Copies the spans from the region <code>start...end</code> in
 * <code>source</code> to the region
 * <code>destoff...destoff+end-start</code> in <code>dest</code>.
 * Spans in <code>source</code> that begin before <code>start</code>
 * or end after <code>end</code> but overlap this range are trimmed
 * as if they began at <code>start</code> or ended at <code>end</code>.
 * Only SuggestionSpans that don't have the SPAN_PARAGRAPH span are copied.
 *
 * This code is almost entirely taken from {@link TextUtils#copySpansFrom}, except for the
 * kind of span that is copied.
 *
 * @throws IndexOutOfBoundsException if any of the copied spans
 * are out of range in <code>dest</code>.
 */
public static void copyNonParagraphSuggestionSpansFrom(Spanned source, int start, int end,
        Spannable dest, int destoff) {
    Object[] spans = source.getSpans(start, end, SuggestionSpan.class);

    for (int i = 0; i < spans.length; i++) {
        int fl = source.getSpanFlags(spans[i]);
        // We don't care about the PARAGRAPH flag in LatinIME code. However, if this flag
        // is set, Spannable#setSpan will throw an exception unless the span is on the edge
        // of a word. But the spans have been split into two by the getText{Before,After}Cursor
        // methods, so after concatenation they may end in the middle of a word.
        // Since we don't use them, we can just remove them and avoid crashing.
        fl &= ~Spanned.SPAN_PARAGRAPH;

        int st = source.getSpanStart(spans[i]);
        int en = source.getSpanEnd(spans[i]);

        if (st < start)
            st = start;
        if (en > end)
            en = end;

        dest.setSpan(spans[i], st - start + destoff, en - start + destoff,
                     fl);
    }
}
 
Example 3
Source File: TextUtils.java    From JotaTextEditor with Apache License 2.0 6 votes vote down vote up
/**
 * Debugging tool to print the spans in a CharSequence.  The output will
 * be printed one span per line.  If the CharSequence is not a Spanned,
 * then the entire string will be printed on a single line.
 */
public static void dumpSpans(CharSequence cs, Printer printer, String prefix) {
    if (cs instanceof Spanned) {
        Spanned sp = (Spanned) cs;
        Object[] os = sp.getSpans(0, cs.length(), Object.class);

        for (int i = 0; i < os.length; i++) {
            Object o = os[i];
            printer.println(prefix + cs.subSequence(sp.getSpanStart(o),
                    sp.getSpanEnd(o)) + ": "
                    + Integer.toHexString(System.identityHashCode(o))
                    + " " + o.getClass().getCanonicalName()
                     + " (" + sp.getSpanStart(o) + "-" + sp.getSpanEnd(o)
                     + ") fl=#" + sp.getSpanFlags(o));
        }
    } else {
        printer.println(prefix + cs + ": (no spans)");
    }
}
 
Example 4
Source File: HtmlCompat.java    From HtmlCompat with Apache License 2.0 5 votes vote down vote up
private static String getTextStyles(Spanned text, int start, int end,
                                    boolean forceNoVerticalMargin, boolean includeTextAlign) {
    String margin = null;
    String textAlign = null;
    if (forceNoVerticalMargin) {
        margin = "margin-top:0; margin-bottom:0;";
    }
    if (includeTextAlign) {
        final AlignmentSpan[] alignmentSpans = text.getSpans(start, end, AlignmentSpan.class);
        // Only use the last AlignmentSpan with flag SPAN_PARAGRAPH
        for (int i = alignmentSpans.length - 1; i >= 0; i--) {
            AlignmentSpan s = alignmentSpans[i];
            if ((text.getSpanFlags(s) & Spanned.SPAN_PARAGRAPH) == Spanned.SPAN_PARAGRAPH) {
                final Layout.Alignment alignment = s.getAlignment();
                if (alignment == Layout.Alignment.ALIGN_NORMAL) {
                    textAlign = "text-align:start;";
                } else if (alignment == Layout.Alignment.ALIGN_CENTER) {
                    textAlign = "text-align:center;";
                } else if (alignment == Layout.Alignment.ALIGN_OPPOSITE) {
                    textAlign = "text-align:end;";
                }
                break;
            }
        }
    }
    if (margin == null && textAlign == null) {
        return "";
    }
    final StringBuilder style = new StringBuilder(" style=\"");
    if (margin != null && textAlign != null) {
        style.append(margin).append(" ").append(textAlign);
    } else if (margin != null) {
        style.append(margin);
    } else if (textAlign != null) {
        style.append(textAlign);
    }
    return style.append("\"").toString();
}
 
Example 5
Source File: RecipientsEditor.java    From bcm-android with GNU General Public License v3.0 5 votes vote down vote up
private static int getSpanLength(Spanned sp, int start, int end, Context context) {
    // TODO: there's a situation where the span can lose its annotations:
    //   - add an auto-complete contact
    //   - add another auto-complete contact
    //   - delete that second contact and keep deleting into the first
    //   - we lose the annotation and can no longer get the span.
    // Need to fix this case because it breaks auto-complete contacts with commas in the name.
    Annotation[] a = sp.getSpans(start, end, Annotation.class);
    if (a.length > 0) {
        return sp.getSpanEnd(a[0]);
    }
    return 0;
}
 
Example 6
Source File: RecipientsEditor.java    From bcm-android with GNU General Public License v3.0 5 votes vote down vote up
private static String getFieldAt(String field, Spanned sp, int start, int end,
        Context context) {
    Annotation[] a = sp.getSpans(start, end, Annotation.class);
    String fieldValue = getAnnotation(a, field);
    if (TextUtils.isEmpty(fieldValue)) {
        fieldValue = TextUtils.substring(sp, start, end);
    }
    return fieldValue;

}
 
Example 7
Source File: DisplayManager.java    From brailleback with Apache License 2.0 5 votes vote down vote up
/**
 * Marks selection spans in the overlaid braille, and returns the position
 * in braille where the first selection begins. If there are no selection
 * spans, returns -1.
 */
private int markSelection(Spanned spanned) {
    DisplaySpans.SelectionSpan[] spans =
            spanned.getSpans(0, spanned.length(),
                    DisplaySpans.SelectionSpan.class);
    int selectionStart = -1;
    for (DisplaySpans.SelectionSpan span : spans) {
  int start =
      textToDisplayPosition(
          currentTranslationResult, cursorPositionToTranslate, spanned.getSpanStart(span));
  int end =
      textToDisplayPosition(
          currentTranslationResult, cursorPositionToTranslate, spanned.getSpanEnd(span));
  if (start == -1 || end == -1) {
    return -1;
  }
        if (start == end) {
            end = start + 1;
        }
  if (end > brailleContent.length) {
            extendContentForCursor();
        }
        copyOverlaidContent();
  for (int i = start; i < end && i < overlaidBrailleContent.length; ++i) {
    overlaidBrailleContent[i] |= (byte) SELECTION_DOTS;
        }
        if (selectionStart == -1) {
            selectionStart = start;
        }
    }
    return selectionStart;
}
 
Example 8
Source File: SpannableStringUtilsTests.java    From Indic-Keyboard with Apache License 2.0 5 votes vote down vote up
private static void assertSpanCount(final int expectedCount, final CharSequence cs) {
    final int actualCount;
    if (cs instanceof Spanned) {
        final Spanned spanned = (Spanned) cs;
        actualCount = spanned.getSpans(0, spanned.length(), Object.class).length;
    } else {
        actualCount = 0;
    }
    assertEquals(expectedCount, actualCount);
}
 
Example 9
Source File: SimpleChipSpan.java    From revolution-irc with GNU General Public License v3.0 5 votes vote down vote up
@Override
public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
    SimpleChipDrawable chipDrawable = ((SimpleChipDrawable) getDrawable());
    Paint myPaint = chipDrawable.getPaint();
    if (text instanceof Spanned) {
        Spanned spannable = (Spanned) text;
        int style = 0;
        int fgColor = -1;
        int fgColorS = -1;
        for (Object o : spannable.getSpans(start, end, Object.class)) {
            int spanStart = spannable.getSpanStart(o);
            if (spanStart > start)
                continue;
            if (o instanceof ForegroundColorSpan) {
                if (spanStart > fgColorS) {
                    fgColor = ((ForegroundColorSpan) o).getForegroundColor();
                    fgColorS = spanStart;
                }
            } else if (o instanceof BackgroundColorSpan) {
                int c = paint.getColor();
                paint.setColor(((BackgroundColorSpan) o).getBackgroundColor());
                canvas.drawRect(x, top, x + chipDrawable.getBounds().width(), bottom, paint);
                paint.setColor(c);
            } else if (o instanceof StyleSpan) {
                style |= ((StyleSpan) o).getStyle();
            }
        }
        if (myPaint != null) {
            if (fgColor != -1)
                myPaint.setColor(fgColor);
            else
                chipDrawable.setDefaultTextColor();
            myPaint.setTypeface(Typeface.create(Typeface.DEFAULT, style));
        }
    }
    super.draw(canvas, text, start, end, x, top, y, bottom, paint);
}
 
Example 10
Source File: KnifeParser.java    From Knife with Apache License 2.0 5 votes vote down vote up
private static void withinHtml(StringBuilder out, Spanned text) {
    int next;

    for (int i = 0; i < text.length(); i = next) {
        next = text.nextSpanTransition(i, text.length(), ParagraphStyle.class);

        ParagraphStyle[] styles = text.getSpans(i, next, ParagraphStyle.class);
        if (styles.length == 2) {
            if (styles[0] instanceof BulletSpan && styles[1] instanceof QuoteSpan) {
                // Let a <br> follow the BulletSpan or QuoteSpan end, so next++
                withinBulletThenQuote(out, text, i, next++);
            } else if (styles[0] instanceof QuoteSpan && styles[1] instanceof BulletSpan) {
                withinQuoteThenBullet(out, text, i, next++);
            } else {
                withinContent(out, text, i, next);
            }
        } else if (styles.length == 1) {
            if (styles[0] instanceof BulletSpan) {
                withinBullet(out, text, i, next++);
            } else if (styles[0] instanceof QuoteSpan) {
                withinQuote(out, text, i, next++);
            } else {
                withinContent(out, text, i, next);
            }
        } else {
            withinContent(out, text, i, next);
        }
    }
}
 
Example 11
Source File: Html.java    From Nimingban with Apache License 2.0 5 votes vote down vote up
private static void withinHtml(StringBuilder out, Spanned text) {
    int len = text.length();

    int next;
    for (int i = 0; i < text.length(); i = next) {
        next = text.nextSpanTransition(i, len, ParagraphStyle.class);
        ParagraphStyle[] style = text.getSpans(i, next, ParagraphStyle.class);
        String elements = " ";
        boolean needDiv = false;

        for(int j = 0; j < style.length; j++) {
            if (style[j] instanceof AlignmentSpan) {
                Layout.Alignment align =
                        ((AlignmentSpan) style[j]).getAlignment();
                needDiv = true;
                if (align == Layout.Alignment.ALIGN_CENTER) {
                    elements = "align=\"center\" " + elements;
                } else if (align == Layout.Alignment.ALIGN_OPPOSITE) {
                    elements = "align=\"right\" " + elements;
                } else {
                    elements = "align=\"left\" " + elements;
                }
            }
        }
        if (needDiv) {
            out.append("<div ").append(elements).append(">");
        }

        withinDiv(out, text, i, next);

        if (needDiv) {
            out.append("</div>");
        }
    }
}
 
Example 12
Source File: HtmlCompat.java    From HtmlCompat with Apache License 2.0 5 votes vote down vote up
private static void encodeTextAlignmentByDiv(Context context, StringBuilder out, Spanned text, int option) {
    int len = text.length();
    int next;
    for (int i = 0; i < len; i = next) {
        next = text.nextSpanTransition(i, len, ParagraphStyle.class);
        ParagraphStyle[] styles = text.getSpans(i, next, ParagraphStyle.class);
        String elements = " ";
        boolean needDiv = false;
        for (ParagraphStyle style : styles) {
            if (style instanceof AlignmentSpan) {
                Layout.Alignment align =
                        ((AlignmentSpan) style).getAlignment();
                needDiv = true;
                if (align == Layout.Alignment.ALIGN_CENTER) {
                    elements = "align=\"center\" " + elements;
                } else if (align == Layout.Alignment.ALIGN_OPPOSITE) {
                    elements = "align=\"right\" " + elements;
                } else {
                    elements = "align=\"left\" " + elements;
                }
            }
        }
        if (needDiv) {
            out.append("<div ").append(elements).append(">");
        }
        withinDiv(context, out, text, i, next, option);
        if (needDiv) {
            out.append("</div>");
        }
    }
}
 
Example 13
Source File: ConverterSpannedToHtml.java    From memoir with Apache License 2.0 5 votes vote down vote up
private Set<SingleParagraphStyle> getParagraphStyles(final Spanned text, Selection selection) {
    Set<SingleParagraphStyle> styles = new HashSet<>();

    for (ParagraphStyle style : text.getSpans(selection.start(), selection.end(), ParagraphStyle.class)) {
        ParagraphType type = ParagraphType.getInstance(style);
        if (type != null) {
            styles.add(new SingleParagraphStyle(type, style));
        }
    }

    return styles;
}
 
Example 14
Source File: SuggestionSpanUtilsTest.java    From Indic-Keyboard with Apache License 2.0 5 votes vote down vote up
private static void assertNotSuggestionSpan(final String expectedText,
        final CharSequence actualText) {
    assertTrue(TextUtils.equals(expectedText, actualText));
    if (!(actualText instanceof Spanned)) {
        return;
    }
    final Spanned spanned = (Spanned)actualText;
    final SuggestionSpan[] suggestionSpans = spanned.getSpans(0, spanned.length(),
            SuggestionSpan.class);
    assertEquals(0, suggestionSpans.length);
}
 
Example 15
Source File: ReactTextView.java    From react-native-GPay with MIT License 5 votes vote down vote up
@Override
public void invalidateDrawable(Drawable drawable) {
  if (mContainsImages && getText() instanceof Spanned) {
    Spanned text = (Spanned) getText();
    TextInlineImageSpan[] spans = text.getSpans(0, text.length(), TextInlineImageSpan.class);
    for (TextInlineImageSpan span : spans) {
      if (span.getDrawable() == drawable) {
        invalidate();
      }
    }
  }
  super.invalidateDrawable(drawable);
}
 
Example 16
Source File: TextUtils.java    From JotaTextEditor with Apache License 2.0 4 votes vote down vote up
/**
     * Flatten a CharSequence and whatever styles can be copied across processes
     * into the parcel.
     */
    public static void writeToParcel(CharSequence cs, Parcel p,
            int parcelableFlags) {
        if (cs instanceof Spanned) {
            p.writeInt(0);
            p.writeString(cs.toString());

            Spanned sp = (Spanned) cs;
            Object[] os = sp.getSpans(0, cs.length(), Object.class);

            // note to people adding to this: check more specific types
            // before more generic types.  also notice that it uses
            // "if" instead of "else if" where there are interfaces
            // so one object can be several.

            for (int i = 0; i < os.length; i++) {
                Object o = os[i];
                Object prop = os[i];

                if (prop instanceof CharacterStyle) {
                    prop = ((CharacterStyle) prop).getUnderlying();
                }

                if (prop instanceof ParcelableSpan) {
                    ParcelableSpan ps = (ParcelableSpan)prop;

                    // dont percel unknown span id
                    int id = ps.getSpanTypeId();
                    if ( id <= ANNOTATION ){
                        p.writeInt(id);
                        ps.writeToParcel(p, parcelableFlags);
                        writeWhere(p, sp, o);
                    }
//                    p.writeInt(ps.getSpanTypeId());
//                    ps.writeToParcel(p, parcelableFlags);
//                    writeWhere(p, sp, o);
                }
            }

            p.writeInt(0);
        } else {
            p.writeInt(1);
            if (cs != null) {
                p.writeString(cs.toString());
            } else {
                p.writeString(null);
            }
        }
    }
 
Example 17
Source File: TextUtils.java    From PowerFileExplorer with GNU General Public License v3.0 4 votes vote down vote up
/**
     * Flatten a CharSequence and whatever styles can be copied across processes
     * into the parcel.
     */
    public static void writeToParcel(CharSequence cs, Parcel p,
            int parcelableFlags) {
        if (cs instanceof Spanned) {
            p.writeInt(0);
            p.writeString(cs.toString());

            Spanned sp = (Spanned) cs;
            Object[] os = sp.getSpans(0, cs.length(), Object.class);

            // note to people adding to this: check more specific types
            // before more generic types.  also notice that it uses
            // "if" instead of "else if" where there are interfaces
            // so one object can be several.

            for (int i = 0; i < os.length; i++) {
                Object o = os[i];
                Object prop = os[i];

                if (prop instanceof CharacterStyle) {
                    prop = ((CharacterStyle) prop).getUnderlying();
                }

                if (prop instanceof ParcelableSpan) {
                    ParcelableSpan ps = (ParcelableSpan)prop;

                    // dont percel unknown span id
                    int id = ps.getSpanTypeId();
                    if ( id <= ANNOTATION ){
                        p.writeInt(id);
                        ps.writeToParcel(p, parcelableFlags);
                        writeWhere(p, sp, o);
                    }
//                    p.writeInt(ps.getSpanTypeId());
//                    ps.writeToParcel(p, parcelableFlags);
//                    writeWhere(p, sp, o);
                }
            }

            p.writeInt(0);
        } else {
            p.writeInt(1);
            if (cs != null) {
                p.writeString(cs.toString());
            } else {
                p.writeString(null);
            }
        }
    }
 
Example 18
Source File: TextRange.java    From AOSP-Kayboard-7.1.2 with Apache License 2.0 4 votes vote down vote up
/**
 * Gets the suggestion spans that are put squarely on the word, with the exact start
 * and end of the span matching the boundaries of the word.
 * @return the list of spans.
 */
public SuggestionSpan[] getSuggestionSpansAtWord() {
    if (!(mTextAtCursor instanceof Spanned && mWord instanceof Spanned)) {
        return new SuggestionSpan[0];
    }
    final Spanned text = (Spanned)mTextAtCursor;
    // Note: it's fine to pass indices negative or greater than the length of the string
    // to the #getSpans() method. The reason we need to get from -1 to +1 is that, the
    // spans were cut at the cursor position, and #getSpans(start, end) does not return
    // spans that end at `start' or begin at `end'. Consider the following case:
    //              this| is          (The | symbolizes the cursor position
    //              ---- ---
    // In this case, the cursor is in position 4, so the 0~7 span has been split into
    // a 0~4 part and a 4~7 part.
    // If we called #getSpans(0, 4) in this case, we would only get the part from 0 to 4
    // of the span, and not the part from 4 to 7, so we would not realize the span actually
    // extends from 0 to 7. But if we call #getSpans(-1, 5) we'll get both the 0~4 and
    // the 4~7 spans and we can merge them accordingly.
    // Any span starting more than 1 char away from the word boundaries in any direction
    // does not touch the word, so we don't need to consider it. That's why requesting
    // -1 ~ +1 is enough.
    // Of course this is only relevant if the cursor is at one end of the word. If it's
    // in the middle, the -1 and +1 are not necessary, but they are harmless.
    final SuggestionSpan[] spans = text.getSpans(mWordAtCursorStartIndex - 1,
            mWordAtCursorEndIndex + 1, SuggestionSpan.class);
    int readIndex = 0;
    int writeIndex = 0;
    for (; readIndex < spans.length; ++readIndex) {
        final SuggestionSpan span = spans[readIndex];
        // The span may be null, as we null them when we find duplicates. Cf a few lines
        // down.
        if (null == span) continue;
        // Tentative span start and end. This may be modified later if we realize the
        // same span is also applied to other parts of the string.
        int spanStart = text.getSpanStart(span);
        int spanEnd = text.getSpanEnd(span);
        for (int i = readIndex + 1; i < spans.length; ++i) {
            if (span.equals(spans[i])) {
                // We found the same span somewhere else. Read the new extent of this
                // span, and adjust our values accordingly.
                spanStart = Math.min(spanStart, text.getSpanStart(spans[i]));
                spanEnd = Math.max(spanEnd, text.getSpanEnd(spans[i]));
                // ...and mark the span as processed.
                spans[i] = null;
            }
        }
        if (spanStart == mWordAtCursorStartIndex && spanEnd == mWordAtCursorEndIndex) {
            // If the span does not start and stop here, ignore it. It probably extends
            // past the start or end of the word, as happens in missing space correction
            // or EasyEditSpans put by voice input.
            spans[writeIndex++] = spans[readIndex];
        }
    }
    return writeIndex == readIndex ? spans : Arrays.copyOfRange(spans, 0, writeIndex);
}
 
Example 19
Source File: FlowTextHelperImpl.java    From Overchan-Android with GNU General Public License v3.0 4 votes vote down vote up
public static int getFloatingPosition(Spanned spanned) {
    for (FloatingMarginSpan span : spanned.getSpans(0, spanned.length(), FloatingMarginSpan.class)) {
        return spanned.getSpanEnd(span);
    }
    return -1;
}
 
Example 20
Source File: HtmlCompat.java    From HtmlCompat with Apache License 2.0 4 votes vote down vote up
private static void withinBlockquoteIndividual(Context context, StringBuilder out, Spanned text,
                                               int start, int end) {
    boolean isInList = false;
    int next;
    for (int i = start; i <= end; i = next) {
        next = TextUtils.indexOf(text, '\n', i, end);
        if (next < 0) {
            next = end;
        }
        if (next == i) {
            if (isInList) {
                // Current paragraph is no longer a list item; close the previously opened list
                isInList = false;
                out.append("</ul>\n");
            }
            out.append("<br>\n");
        } else {
            boolean isListItem = false;
            ParagraphStyle[] paragraphStyles = text.getSpans(i, next, ParagraphStyle.class);
            for (ParagraphStyle paragraphStyle : paragraphStyles) {
                final int spanFlags = text.getSpanFlags(paragraphStyle);
                if ((spanFlags & Spanned.SPAN_PARAGRAPH) == Spanned.SPAN_PARAGRAPH
                        && paragraphStyle instanceof BulletSpan) {
                    isListItem = true;
                    break;
                }
            }
            if (isListItem && !isInList) {
                // Current paragraph is the first item in a list
                isInList = true;
                out.append("<ul")
                   .append(getTextStyles(text, i, next, true, false))
                   .append(">\n");
            }
            if (isInList && !isListItem) {
                // Current paragraph is no longer a list item; close the previously opened list
                isInList = false;
                out.append("</ul>\n");
            }
            String tagType = isListItem ? "li" : "p";
            out.append("<").append(tagType)
               .append(getTextDirection(text, i, next))
               .append(getTextStyles(text, i, next, !isListItem, true))
               .append(">");
            withinParagraph(context, out, text, i, next);
            out.append("</");
            out.append(tagType);
            out.append(">\n");
            if (next == end && isInList) {
                isInList = false;
                out.append("</ul>\n");
            }
        }
        next++;
    }
}