Java Code Examples for android.text.Spannable#getSpanFlags()

The following examples show how to use android.text.Spannable#getSpanFlags() . 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: BaseInputConnection.java    From android_9.0.0_r45 with Apache License 2.0 6 votes vote down vote up
/** @hide */
public static void setComposingSpans(Spannable text, int start, int end) {
    final Object[] sps = text.getSpans(start, end, Object.class);
    if (sps != null) {
        for (int i=sps.length-1; i>=0; i--) {
            final Object o = sps[i];
            if (o == COMPOSING) {
                text.removeSpan(o);
                continue;
            }

            final int fl = text.getSpanFlags(o);
            if ((fl & (Spanned.SPAN_COMPOSING | Spanned.SPAN_POINT_MARK_MASK))
                    != (Spanned.SPAN_COMPOSING | Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)) {
                text.setSpan(o, text.getSpanStart(o), text.getSpanEnd(o),
                        (fl & ~Spanned.SPAN_POINT_MARK_MASK)
                                | Spanned.SPAN_COMPOSING
                                | Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
        }
    }

    text.setSpan(COMPOSING, start, end,
            Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | Spanned.SPAN_COMPOSING);
}
 
Example 2
Source File: SpannableStringHelper.java    From revolution-irc with GNU General Public License v3.0 6 votes vote down vote up
public static void setAndMergeSpans(Spannable text, Object what, int start, int end, int flags) {
    Object[] spans = text.getSpans(Math.max(start - 1, 0), Math.min(end + 1, 0), what.getClass());
    for (Object span : spans) {
        if (!areSpansEqual(span, what))
            continue;
        int sFlags = text.getSpanFlags(span);
        if ((sFlags & Spanned.SPAN_COMPOSING) != 0)
            continue;

        int sStart = text.getSpanStart(span);
        int sEnd = text.getSpanEnd(span);
        if (sEnd < start || sStart > end)
            continue;
        text.removeSpan(span);
        if (sStart < start)
            start = sStart;
        if (sEnd > end)
            end = sEnd;
    }
    text.setSpan(what, start, end, flags);
}
 
Example 3
Source File: AnchorHeadingPlugin.java    From Markwon with Apache License 2.0 6 votes vote down vote up
@Override
public void afterSetText(@NonNull TextView textView) {
    final Spannable spannable = (Spannable) textView.getText();
    // obtain heading spans
    final HeadingSpan[] spans = spannable.getSpans(0, spannable.length(), HeadingSpan.class);
    if (spans != null) {
        for (HeadingSpan span : spans) {
            final int start = spannable.getSpanStart(span);
            final int end = spannable.getSpanEnd(span);
            final int flags = spannable.getSpanFlags(span);
            spannable.setSpan(
                    new AnchorSpan(createAnchor(spannable.subSequence(start, end))),
                    start,
                    end,
                    flags
            );
        }
    }
}
 
Example 4
Source File: BaseInputConnection.java    From android_9.0.0_r45 with Apache License 2.0 5 votes vote down vote up
public static final void removeComposingSpans(Spannable text) {
    text.removeSpan(COMPOSING);
    Object[] sps = text.getSpans(0, text.length(), Object.class);
    if (sps != null) {
        for (int i=sps.length-1; i>=0; i--) {
            Object o = sps[i];
            if ((text.getSpanFlags(o)&Spanned.SPAN_COMPOSING) != 0) {
                text.removeSpan(o);
            }
        }
    }
}
 
Example 5
Source File: AccessibilityNodeInfo.java    From android_9.0.0_r45 with Apache License 2.0 5 votes vote down vote up
/**
 * Sets the text of this node.
 * <p>
 *   <strong>Note:</strong> Cannot be called from an
 *   {@link android.accessibilityservice.AccessibilityService}.
 *   This class is made immutable before being delivered to an AccessibilityService.
 * </p>
 *
 * @param text The text.
 *
 * @throws IllegalStateException If called from an AccessibilityService.
 */
public void setText(CharSequence text) {
    enforceNotSealed();
    mOriginalText = text;
    // Replace any ClickableSpans in mText with placeholders
    if (text instanceof Spanned) {
        ClickableSpan[] spans =
                ((Spanned) text).getSpans(0, text.length(), ClickableSpan.class);
        if (spans.length > 0) {
            Spannable spannable = new SpannableStringBuilder(text);
            for (int i = 0; i < spans.length; i++) {
                ClickableSpan span = spans[i];
                if ((span instanceof AccessibilityClickableSpan)
                        || (span instanceof AccessibilityURLSpan)) {
                    // We've already done enough
                    break;
                }
                int spanToReplaceStart = spannable.getSpanStart(span);
                int spanToReplaceEnd = spannable.getSpanEnd(span);
                int spanToReplaceFlags = spannable.getSpanFlags(span);
                spannable.removeSpan(span);
                ClickableSpan replacementSpan = (span instanceof URLSpan)
                        ? new AccessibilityURLSpan((URLSpan) span)
                        : new AccessibilityClickableSpan(span.getId());
                spannable.setSpan(replacementSpan, spanToReplaceStart, spanToReplaceEnd,
                        spanToReplaceFlags);
            }
            mText = spannable;
            return;
        }
    }
    mText = (text == null) ? null : text.subSequence(0, text.length());
}
 
Example 6
Source File: MetaKeyKeyListener.java    From android_9.0.0_r45 with Apache License 2.0 5 votes vote down vote up
private static void adjust(Spannable content, Object what) {
    int current = content.getSpanFlags(what);

    if (current == PRESSED)
        content.setSpan(what, 0, 0, USED);
    else if (current == RELEASED)
        content.removeSpan(what);
}
 
Example 7
Source File: RichEditor.java    From RichEditor with MIT License 5 votes vote down vote up
private <T extends Styleable> int endStyle(int offset, Spannable spannable, Class<T> clazz) {
    T[] spans = spannable.getSpans(offset, offset, clazz);
    if (spans != null && spans.length > 0) {
        T s = spans[0];
        int flags = spannable.getSpanFlags(s);
        if (flags != Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) {
            terminateStyle(spannable, s);
            return StyleTypeStateSpec.StyleTypeState.STATE_EXIST;
        } else {
            spannable.removeSpan(s);
            return StyleTypeStateSpec.StyleTypeState.STATE_NONE;
        }
    }
    return StyleTypeStateSpec.StyleTypeState.STATE_NONE;
}
 
Example 8
Source File: RichEditor.java    From RichEditor with MIT License 5 votes vote down vote up
private int[] getStyleTypeState(int start, int end, Spannable spannable) {
    Styleable[] styleables = spannable.getSpans(start, end, Styleable.class);
    if (styleables != null && styleables.length > 0) {
        int[] types = new int[styleables.length];
        for (int i = 0; i < styleables.length; i++) {
            int type = styleables[i].getStyleType();
            Style style = Style.get(type);
            int t;
            int flag = spannable.getSpanFlags(styleables[i]);
            if (style instanceof StyleExt) {
                //noinspection unchecked
                t = ((StyleExt) style).getStyleTypeState(flag, styleables[i]);
            } else {
                int state;
                if (flag == Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) {
                    state = StyleTypeStateSpec.StyleTypeState.STATE_EXIST;
                } else {
                    state = StyleTypeStateSpec.StyleTypeState.STATE_ACTIVE;
                }
                t = StyleTypeStateSpec.makeStyleTypeStateSpec(type, state);
            }
            types[i] = t;
        }
        return types;
    } else {
        return new int[0];
    }
}
 
Example 9
Source File: MetaKeyKeyListener.java    From android_9.0.0_r45 with Apache License 2.0 4 votes vote down vote up
private static void resetLock(Spannable content, Object what) {
    int current = content.getSpanFlags(what);

    if (current == LOCKED)
        content.removeSpan(what);
}
 
Example 10
Source File: LocaleSpanCompatUtils.java    From AOSP-Kayboard-7.1.2 with Apache License 2.0 4 votes vote down vote up
/**
 * Ensures that the specified range is covered with only one {@link LocaleSpan} with the given
 * locale. If the region is already covered by one or more {@link LocaleSpan}, their ranges are
 * updated so that each character has only one locale.
 * @param spannable the spannable object to be updated.
 * @param start the start index from which {@link LocaleSpan} is attached (inclusive).
 * @param end the end index to which {@link LocaleSpan} is attached (exclusive).
 * @param locale the locale to be attached to the specified range.
 */
@UsedForTesting
public static void updateLocaleSpan(final Spannable spannable, final int start,
        final int end, final Locale locale) {
    if (end < start) {
        Log.e(TAG, "Invalid range: start=" + start + " end=" + end);
        return;
    }
    if (!isLocaleSpanAvailable()) {
        return;
    }
    // A brief summary of our strategy;
    //   1. Enumerate all LocaleSpans between [start - 1, end + 1].
    //   2. For each LocaleSpan S:
    //      - Update the range of S so as not to cover [start, end] if S doesn't have the
    //        expected locale.
    //      - Mark S as "to be merged" if S has the expected locale.
    //   3. Merge all the LocaleSpans that are marked as "to be merged" into one LocaleSpan.
    //      If no appropriate span is found, create a new one with newLocaleSpan method.
    final int searchStart = Math.max(start - 1, 0);
    final int searchEnd = Math.min(end + 1, spannable.length());
    // LocaleSpans found in the target range. See the step 1 in the above comment.
    final Object[] existingLocaleSpans = spannable.getSpans(searchStart, searchEnd,
            LOCALE_SPAN_TYPE);
    // LocaleSpans that are marked as "to be merged". See the step 2 in the above comment.
    final ArrayList<Object> existingLocaleSpansToBeMerged = new ArrayList<>();
    boolean isStartExclusive = true;
    boolean isEndExclusive = true;
    int newStart = start;
    int newEnd = end;
    for (final Object existingLocaleSpan : existingLocaleSpans) {
        final Locale attachedLocale = getLocaleFromLocaleSpan(existingLocaleSpan);
        if (!locale.equals(attachedLocale)) {
            // This LocaleSpan does not have the expected locale. Update its range if it has
            // an intersection with the range [start, end] (the first case of the step 2 in the
            // above comment).
            removeLocaleSpanFromRange(existingLocaleSpan, spannable, start, end);
            continue;
        }
        final int spanStart = spannable.getSpanStart(existingLocaleSpan);
        final int spanEnd = spannable.getSpanEnd(existingLocaleSpan);
        if (spanEnd < spanStart) {
            Log.e(TAG, "Invalid span: spanStart=" + spanStart + " spanEnd=" + spanEnd);
            continue;
        }
        if (spanEnd < start || end < spanStart) {
            // No intersection found.
            continue;
        }

        // Here existingLocaleSpan has the expected locale and an intersection with the
        // range [start, end] (the second case of the the step 2 in the above comment).
        final int spanFlag = spannable.getSpanFlags(existingLocaleSpan);
        if (spanStart < newStart) {
            newStart = spanStart;
            isStartExclusive = ((spanFlag & Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) ==
                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        if (newEnd < spanEnd) {
            newEnd = spanEnd;
            isEndExclusive = ((spanFlag & Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) ==
                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        existingLocaleSpansToBeMerged.add(existingLocaleSpan);
    }

    int originalLocaleSpanFlag = 0;
    Object localeSpan = null;
    if (existingLocaleSpansToBeMerged.isEmpty()) {
        // If there is no LocaleSpan that is marked as to be merged, create a new one.
        localeSpan = newLocaleSpan(locale);
    } else {
        // Reuse the first LocaleSpan to avoid unnecessary object instantiation.
        localeSpan = existingLocaleSpansToBeMerged.get(0);
        originalLocaleSpanFlag = spannable.getSpanFlags(localeSpan);
        // No need to keep other instances.
        for (int i = 1; i < existingLocaleSpansToBeMerged.size(); ++i) {
            spannable.removeSpan(existingLocaleSpansToBeMerged.get(i));
        }
    }
    final int localeSpanFlag = getSpanFlag(originalLocaleSpanFlag, isStartExclusive,
            isEndExclusive);
    spannable.setSpan(localeSpan, newStart, newEnd, localeSpanFlag);
}
 
Example 11
Source File: LocaleSpanCompatUtils.java    From AOSP-Kayboard-7.1.2 with Apache License 2.0 4 votes vote down vote up
private static void removeLocaleSpanFromRange(final Object localeSpan,
        final Spannable spannable, final int removeStart, final int removeEnd) {
    if (!isLocaleSpanAvailable()) {
        return;
    }
    final int spanStart = spannable.getSpanStart(localeSpan);
    final int spanEnd = spannable.getSpanEnd(localeSpan);
    if (spanStart > spanEnd) {
        Log.e(TAG, "Invalid span: spanStart=" + spanStart + " spanEnd=" + spanEnd);
        return;
    }
    if (spanEnd < removeStart) {
        // spanStart < spanEnd < removeStart < removeEnd
        return;
    }
    if (removeEnd < spanStart) {
        // spanStart < removeEnd < spanStart < spanEnd
        return;
    }
    final int spanFlags = spannable.getSpanFlags(localeSpan);
    if (spanStart < removeStart) {
        if (removeEnd < spanEnd) {
            // spanStart < removeStart < removeEnd < spanEnd
            final Locale locale = getLocaleFromLocaleSpan(localeSpan);
            spannable.setSpan(localeSpan, spanStart, removeStart, spanFlags);
            final Object attionalLocaleSpan = newLocaleSpan(locale);
            spannable.setSpan(attionalLocaleSpan, removeEnd, spanEnd, spanFlags);
            return;
        }
        // spanStart < removeStart < spanEnd <= removeEnd
        spannable.setSpan(localeSpan, spanStart, removeStart, spanFlags);
        return;
    }
    if (removeEnd < spanEnd) {
        // removeStart <= spanStart < removeEnd < spanEnd
        spannable.setSpan(localeSpan, removeEnd, spanEnd, spanFlags);
        return;
    }
    // removeStart <= spanStart < spanEnd < removeEnd
    spannable.removeSpan(localeSpan);
}
 
Example 12
Source File: IRCColorUtils.java    From revolution-irc with GNU General Public License v3.0 4 votes vote down vote up
public static String convertSpannableToIRCString(Context context, Spannable spannable) {
    int n;
    int pFg = 99;
    int pBg = 99;
    boolean pBold = false;
    boolean pItalic = false;
    boolean pUnderline = false;
    StringBuilder ret = new StringBuilder(spannable.length());
    for (int i = 0; i < spannable.length(); i = n) {
        n = spannable.nextSpanTransition(i, spannable.length(), Object.class);
        int fg = 99;
        int bg = 99;
        boolean bold = false;
        boolean italic = false;
        boolean underline = false;
        for (Object span : spannable.getSpans(i, n, Object.class)) {
            int flags = spannable.getSpanFlags(span);
            if ((flags & Spannable.SPAN_COMPOSING) != 0)
                continue;
            if (span instanceof ForegroundColorSpan) {
                fg = findNearestIRCColor(context, ((ForegroundColorSpan) span).getForegroundColor());
            } else if (span instanceof BackgroundColorSpan) {
                bg = findNearestIRCColor(context, ((BackgroundColorSpan) span).getBackgroundColor());
            } else if (span instanceof StyleSpan) {
                int style = ((StyleSpan) span).getStyle();
                if (style == Typeface.BOLD || style == Typeface.BOLD_ITALIC)
                    bold = true;
                if (style == Typeface.ITALIC || style == Typeface.BOLD_ITALIC)
                    italic = true;
            } else if (span instanceof UnderlineSpan) {
                underline = true;
            }
        }
        if ((!bold && pBold) || (!italic && pItalic) || (!underline && pUnderline)) {
            ret.append((char) 0x0F);
            pFg = -1;
            pBg = -1;
            pBold = false;
            pItalic = false;
            pUnderline = false;
        }
        if (bold && !pBold)
            ret.append((char) 0x02);
        if (italic && !pItalic)
            ret.append((char) 0x1D);
        if (underline && !pUnderline)
            ret.append((char) 0x1F);
        if (fg != pFg || bg != pBg) {
            ret.append((char) 0x03);
            ret.append(fg);
            ret.append(',');
            ret.append(bg);
        }

        pFg = fg;
        pBg = bg;
        pBold = bold;
        pItalic = italic;
        pUnderline = underline;
        ret.append(spannable, i, n);
    }
    return ret.toString();
}
 
Example 13
Source File: LocaleSpanCompatUtils.java    From Indic-Keyboard with Apache License 2.0 4 votes vote down vote up
/**
 * Ensures that the specified range is covered with only one {@link LocaleSpan} with the given
 * locale. If the region is already covered by one or more {@link LocaleSpan}, their ranges are
 * updated so that each character has only one locale.
 * @param spannable the spannable object to be updated.
 * @param start the start index from which {@link LocaleSpan} is attached (inclusive).
 * @param end the end index to which {@link LocaleSpan} is attached (exclusive).
 * @param locale the locale to be attached to the specified range.
 */
@UsedForTesting
public static void updateLocaleSpan(final Spannable spannable, final int start,
        final int end, final Locale locale) {
    if (end < start) {
        Log.e(TAG, "Invalid range: start=" + start + " end=" + end);
        return;
    }
    if (!isLocaleSpanAvailable()) {
        return;
    }
    // A brief summary of our strategy;
    //   1. Enumerate all LocaleSpans between [start - 1, end + 1].
    //   2. For each LocaleSpan S:
    //      - Update the range of S so as not to cover [start, end] if S doesn't have the
    //        expected locale.
    //      - Mark S as "to be merged" if S has the expected locale.
    //   3. Merge all the LocaleSpans that are marked as "to be merged" into one LocaleSpan.
    //      If no appropriate span is found, create a new one with newLocaleSpan method.
    final int searchStart = Math.max(start - 1, 0);
    final int searchEnd = Math.min(end + 1, spannable.length());
    // LocaleSpans found in the target range. See the step 1 in the above comment.
    final Object[] existingLocaleSpans = spannable.getSpans(searchStart, searchEnd,
            LOCALE_SPAN_TYPE);
    // LocaleSpans that are marked as "to be merged". See the step 2 in the above comment.
    final ArrayList<Object> existingLocaleSpansToBeMerged = new ArrayList<>();
    boolean isStartExclusive = true;
    boolean isEndExclusive = true;
    int newStart = start;
    int newEnd = end;
    for (final Object existingLocaleSpan : existingLocaleSpans) {
        final Locale attachedLocale = getLocaleFromLocaleSpan(existingLocaleSpan);
        if (!locale.equals(attachedLocale)) {
            // This LocaleSpan does not have the expected locale. Update its range if it has
            // an intersection with the range [start, end] (the first case of the step 2 in the
            // above comment).
            removeLocaleSpanFromRange(existingLocaleSpan, spannable, start, end);
            continue;
        }
        final int spanStart = spannable.getSpanStart(existingLocaleSpan);
        final int spanEnd = spannable.getSpanEnd(existingLocaleSpan);
        if (spanEnd < spanStart) {
            Log.e(TAG, "Invalid span: spanStart=" + spanStart + " spanEnd=" + spanEnd);
            continue;
        }
        if (spanEnd < start || end < spanStart) {
            // No intersection found.
            continue;
        }

        // Here existingLocaleSpan has the expected locale and an intersection with the
        // range [start, end] (the second case of the the step 2 in the above comment).
        final int spanFlag = spannable.getSpanFlags(existingLocaleSpan);
        if (spanStart < newStart) {
            newStart = spanStart;
            isStartExclusive = ((spanFlag & Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) ==
                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        if (newEnd < spanEnd) {
            newEnd = spanEnd;
            isEndExclusive = ((spanFlag & Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) ==
                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        existingLocaleSpansToBeMerged.add(existingLocaleSpan);
    }

    int originalLocaleSpanFlag = 0;
    Object localeSpan = null;
    if (existingLocaleSpansToBeMerged.isEmpty()) {
        // If there is no LocaleSpan that is marked as to be merged, create a new one.
        localeSpan = newLocaleSpan(locale);
    } else {
        // Reuse the first LocaleSpan to avoid unnecessary object instantiation.
        localeSpan = existingLocaleSpansToBeMerged.get(0);
        originalLocaleSpanFlag = spannable.getSpanFlags(localeSpan);
        // No need to keep other instances.
        for (int i = 1; i < existingLocaleSpansToBeMerged.size(); ++i) {
            spannable.removeSpan(existingLocaleSpansToBeMerged.get(i));
        }
    }
    final int localeSpanFlag = getSpanFlag(originalLocaleSpanFlag, isStartExclusive,
            isEndExclusive);
    spannable.setSpan(localeSpan, newStart, newEnd, localeSpanFlag);
}
 
Example 14
Source File: LocaleSpanCompatUtils.java    From Indic-Keyboard with Apache License 2.0 4 votes vote down vote up
private static void removeLocaleSpanFromRange(final Object localeSpan,
        final Spannable spannable, final int removeStart, final int removeEnd) {
    if (!isLocaleSpanAvailable()) {
        return;
    }
    final int spanStart = spannable.getSpanStart(localeSpan);
    final int spanEnd = spannable.getSpanEnd(localeSpan);
    if (spanStart > spanEnd) {
        Log.e(TAG, "Invalid span: spanStart=" + spanStart + " spanEnd=" + spanEnd);
        return;
    }
    if (spanEnd < removeStart) {
        // spanStart < spanEnd < removeStart < removeEnd
        return;
    }
    if (removeEnd < spanStart) {
        // spanStart < removeEnd < spanStart < spanEnd
        return;
    }
    final int spanFlags = spannable.getSpanFlags(localeSpan);
    if (spanStart < removeStart) {
        if (removeEnd < spanEnd) {
            // spanStart < removeStart < removeEnd < spanEnd
            final Locale locale = getLocaleFromLocaleSpan(localeSpan);
            spannable.setSpan(localeSpan, spanStart, removeStart, spanFlags);
            final Object attionalLocaleSpan = newLocaleSpan(locale);
            spannable.setSpan(attionalLocaleSpan, removeEnd, spanEnd, spanFlags);
            return;
        }
        // spanStart < removeStart < spanEnd <= removeEnd
        spannable.setSpan(localeSpan, spanStart, removeStart, spanFlags);
        return;
    }
    if (removeEnd < spanEnd) {
        // removeStart <= spanStart < removeEnd < spanEnd
        spannable.setSpan(localeSpan, removeEnd, spanEnd, spanFlags);
        return;
    }
    // removeStart <= spanStart < spanEnd < removeEnd
    spannable.removeSpan(localeSpan);
}