Java Code Examples for android.text.Editable#getSpanEnd()

The following examples show how to use android.text.Editable#getSpanEnd() . 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: AutoCompleteEditText.java    From Carbon with Apache License 2.0 6 votes vote down vote up
@Override
protected void onSelectionChanged(int selStart, int selEnd) {
    if (autoCompleting)
        return;
    if (selStart == selEnd) {
        Editable text = getText();
        HintSpan[] spans = text.getSpans(0, length(), HintSpan.class);
        if (spans.length > 1)
            throw new IllegalStateException("more than one HintSpan");
        autoCompleting = true;
        if (spans.length == 1) {
            HintSpan span = spans[0];
            if (selStart >= text.getSpanStart(span) && selStart < text.getSpanEnd(span)) {
                setSelection(text.getSpanStart(span));
            } else if (selStart == text.getSpanEnd(span)) {
                text.removeSpan(span);
                super.setImeOptions(prevOptions);
            }
        }
    }
    autoComplete();
    autoCompleting = false;
    super.onSelectionChanged(selStart, selEnd);
}
 
Example 2
Source File: TokenCompleteTextView.java    From TokenAutoComplete with Apache License 2.0 6 votes vote down vote up
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    // count > 0 means something will be deleted
    if (count > 0 && getText() != null) {
        Editable text = getText();

        int end = start + count;

        TokenImageSpan[] spans = text.getSpans(start, end, TokenImageSpan.class);

        //NOTE: I'm not completely sure this won't cause problems if we get stuck in a text changed loop
        //but it appears to work fine. Spans will stop getting removed if this breaks.
        ArrayList<TokenImageSpan> spansToRemove = new ArrayList<>();
        for (TokenImageSpan token : spans) {
            if (text.getSpanStart(token) < end && start < text.getSpanEnd(token)) {
                spansToRemove.add(token);
            }
        }
        this.spansToRemove = spansToRemove;
    }
}
 
Example 3
Source File: MentionsEditText.java    From Spyglass with Apache License 2.0 6 votes vote down vote up
/**
 * Temporarily remove MentionSpans that may interfere with composing text. Note that software keyboards are allowed
 * to place arbitrary spans over the text. This was resulting in several bugs in edge cases while handling the
 * MentionSpans while composing text (with different issues for different keyboards). The easiest solution for this
 * is to remove any MentionSpans that could cause issues while the user is changing text.
 *
 * Note: The MentionSpans are added again in {@link #replacePlaceholdersWithCorrespondingMentionSpans(Editable)}
 *
 * @param text the current text before it changes
 */
private void replaceMentionSpansWithPlaceholdersAsNecessary(@NonNull CharSequence text) {
    int index = getSelectionStart();
    int wordStart = findStartOfWord(text, index);
    Editable editable = getText();
    MentionSpan[] mentionSpansInCurrentWord = editable.getSpans(wordStart, index, MentionSpan.class);
    for (MentionSpan span : mentionSpansInCurrentWord) {
        if (span.getDisplayMode() != Mentionable.MentionDisplayMode.NONE) {
            int spanStart = editable.getSpanStart(span);
            int spanEnd = editable.getSpanEnd(span);
            editable.setSpan(new PlaceholderSpan(span, spanStart, spanEnd),
                    spanStart, spanEnd, Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
            editable.removeSpan(span);
        }
    }
}
 
Example 4
Source File: TokenCompleteTextView.java    From TokenAutoComplete with Apache License 2.0 6 votes vote down vote up
/**
 * Remove a span from the current EditText and fire the appropriate callback
 *
 * @param text Editable to remove the span from
 * @param span TokenImageSpan to be removed
 */
private void removeSpan(Editable text, TokenImageSpan span) {
    //We usually add whitespace after a token, so let's try to remove it as well if it's present
    int end = text.getSpanEnd(span);
    if (end < text.length() && text.charAt(end) == ' ') {
        end += 1;
    }

    internalEditInProgress = true;
    text.delete(text.getSpanStart(span), end);
    internalEditInProgress = false;

    if (allowCollapse && !isFocused()) {
        updateCountSpan();
    }
}
 
Example 5
Source File: RichEditText.java    From o2oa with GNU Affero General Public License v3.0 6 votes vote down vote up
@Override
public void afterTextChanged(Editable s) {
    final TagSpan span = willDelSpan;
    log("TagSpanTextWatcher#willRemove#span:" + (span == null ? "null" : span.toString()));
    if (span != null && span.willRemove) {
        int start = s.getSpanStart(span);
        int end = s.getSpanEnd(span);

        // Remove the span
        s.removeSpan(span);

        // Remove the remaining emoticon text.
        if (start != end) {
            s.delete(start, end);
        }
    }
}
 
Example 6
Source File: FixedURLSpan.java    From Conversations with GNU General Public License v3.0 5 votes vote down vote up
public static void fix(final Editable editable) {
	for (final URLSpan urlspan : editable.getSpans(0, editable.length() - 1, URLSpan.class)) {
		final int start = editable.getSpanStart(urlspan);
		final int end = editable.getSpanEnd(urlspan);
		editable.removeSpan(urlspan);
		editable.setSpan(new FixedURLSpan(urlspan.getURL()), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
	}
}
 
Example 7
Source File: TokenCompleteTextView.java    From TokenAutoComplete with Apache License 2.0 5 votes vote down vote up
/**
 * Checks if selection can be deleted. This method is called from TokenInputConnection .
 * @param beforeLength the number of characters before the current selection end to check
 * @return true if there are no non-deletable pieces of the section
 */
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
public boolean canDeleteSelection(int beforeLength) {
    if (getObjects().size() < 1) return true;

    // if beforeLength is 1, we either have no selection or the call is coming from OnKey Event.
    // In these scenarios, getSelectionStart() will return the correct value.

    int endSelection = getSelectionEnd();
    int startSelection = beforeLength == 1 ? getSelectionStart() : endSelection - beforeLength;

    Editable text = getText();
    TokenImageSpan[] spans = text.getSpans(0, text.length(), TokenImageSpan.class);

    // Iterate over all tokens and allow the deletion
    // if there are no tokens not removable in the selection
    for (TokenImageSpan span : spans) {
        int startTokenSelection = text.getSpanStart(span);
        int endTokenSelection = text.getSpanEnd(span);

        // moving on, no need to check this token
        if (isTokenRemovable(span.token)) continue;

        if (startSelection == endSelection) {
            // Delete single
            if (endTokenSelection + 1 == endSelection) {
                return false;
            }
        } else {
            // Delete range
            // Don't delete if a non removable token is in range
            if (startSelection <= startTokenSelection
                    && endTokenSelection + 1 <= endSelection) {
                return false;
            }
        }
    }
    return true;
}
 
Example 8
Source File: NormalStyle.java    From YCCustomText with Apache License 2.0 5 votes vote down vote up
/**
 * 样式情况判断
 * @param editable                      editable
 * @param start                         start
 * @param end                           end
 */
public void applyStyle(Editable editable, int start, int end) {
    //获取 从  start 到 end 位置上所有的指定 class 类型的 Span数组
    E[] spans = editable.getSpans(start, end, clazzE);
    E existingSpan = null;
    if (spans.length > 0) {
        existingSpan = spans[0];
    }
    if (existingSpan == null) {
        //当前选中内部无此样式,开始设置span样式
        checkAndMergeSpan(editable, start, end, clazzE);
    } else {
        //获取 一个 span 的起始位置
        int existingSpanStart = editable.getSpanStart(existingSpan);
        //获取一个span 的结束位置
        int existingSpanEnd = editable.getSpanEnd(existingSpan);
        if (existingSpanStart <= start && existingSpanEnd >= end) {
            //在一个 完整的 span 中
            //当我们选中的区域在一段连续的 Bold 样式里面的时候,再次选择Bold将会取消样式
            //删除 样式
            removeStyle(editable, start, end, clazzE, true);
        } else {
            //当前选中区域存在了某某样式,需要合并样式
            checkAndMergeSpan(editable, start, end, clazzE);
        }
    }
}
 
Example 9
Source File: GroupUsersFragment.java    From actor-platform with GNU Affero General Public License v3.0 5 votes vote down vote up
private void checkForDeletions(Editable editable) {
    Integer[] selected = getSelected();
    boolean hasDeletions = false;
    UserSpan[] spans = editable.getSpans(0, editable.length(), UserSpan.class);
    for (Integer u : selected) {
        boolean founded = false;
        for (UserSpan span : spans) {
            if (span.getUser().getId() == u) {
                if (editable.getSpanStart(span) == editable.getSpanEnd(span)) {
                    break;
                } else {
                    founded = true;
                    break;
                }
            }
        }

        if (!founded) {
            hasDeletions = true;
            unselect(u);
        }
    }
    if (hasDeletions) {
        getActivity().invalidateOptionsMenu();
        getAdapter().notifyDataSetChanged();
    }
}
 
Example 10
Source File: MentionsEditText.java    From Spyglass with Apache License 2.0 5 votes vote down vote up
/**
 * Resets the given {@link MentionSpan} in the editor, forcing it to redraw with its latest drawable state.
 *
 * @param span the {@link MentionSpan} to update
 */
public void updateSpan(@NonNull MentionSpan span) {
    mBlockCompletion = true;
    Editable text = getText();
    int start = text.getSpanStart(span);
    int end = text.getSpanEnd(span);
    if (start >= 0 && end > start && end <= text.length()) {
        text.removeSpan(span);
        text.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    }
    mBlockCompletion = false;
}
 
Example 11
Source File: EditTextCaption.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
private void applyTextStyleToSelection(TypefaceSpan span) {
    int start;
    int end;
    if (selectionStart >= 0 && selectionEnd >= 0) {
        start = selectionStart;
        end = selectionEnd;
        selectionStart = selectionEnd = -1;
    } else {
        start = getSelectionStart();
        end = getSelectionEnd();
    }
    Editable editable = getText();

    CharacterStyle spans[] = editable.getSpans(start, end, CharacterStyle.class);
    if (spans != null && spans.length > 0) {
        for (int a = 0; a < spans.length; a++) {
            CharacterStyle oldSpan = spans[a];
            int spanStart = editable.getSpanStart(oldSpan);
            int spanEnd = editable.getSpanEnd(oldSpan);
            editable.removeSpan(oldSpan);
            if (spanStart < start) {
                editable.setSpan(oldSpan, spanStart, start, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
            if (spanEnd > end) {
                editable.setSpan(oldSpan, end, spanEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
        }
    }
    if (span != null) {
        editable.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    }
    if (delegate != null) {
        delegate.onSpansChanged();
    }
}
 
Example 12
Source File: TokenCompleteTextView.java    From TokenAutoComplete with Apache License 2.0 5 votes vote down vote up
private Range getCurrentCandidateTokenRange() {
    Editable editable = getText();
    int cursorEndPosition = getSelectionEnd();
    int candidateStringStart = prefix.length();
    int candidateStringEnd = editable.length();
    if (hintVisible) {
        //Don't try to search the hint for possible tokenizable strings
        candidateStringEnd = candidateStringStart;
    }

    //We want to find the largest string that contains the selection end that is not already tokenized
    TokenImageSpan[] spans = editable.getSpans(prefix.length(), editable.length(), TokenImageSpan.class);
    for (TokenImageSpan span : spans) {
        int spanEnd = editable.getSpanEnd(span);
        if (candidateStringStart < spanEnd && cursorEndPosition >= spanEnd) {
            candidateStringStart = spanEnd;
        }
        int spanStart = editable.getSpanStart(span);
        if (candidateStringEnd > spanStart && cursorEndPosition <= spanEnd) {
            candidateStringEnd = spanStart;
        }
    }

    List<Range> tokenRanges = tokenizer.findTokenRanges(editable, candidateStringStart, candidateStringEnd);

    for (Range range: tokenRanges) {
        if (range.start <= cursorEndPosition && cursorEndPosition <= range.end) {
            return range;
        }
    }

    return new Range(cursorEndPosition, cursorEndPosition);
}
 
Example 13
Source File: RichUtils.java    From RichEditor with MIT License 5 votes vote down vote up
/**
 * 处理行内样式各个按钮的状态(点亮或置灰)
 *
 * @param type 样式类型
 */
private boolean handleInlineStyleButtonStatus(@RichTypeEnum String type) {
    Editable editable = mRichEditText.getEditableText();
    int cursorPos = mRichEditText.getSelectionEnd();
    IInlineSpan[] inlineSpans = (IInlineSpan[]) editable.getSpans(cursorPos, cursorPos, getSpanClassFromType(type));
    if (inlineSpans.length <= 0) {
        return false;
    }

    boolean isLight = false; //是否点亮

    for (IInlineSpan span : inlineSpans) {
        int spanStart = editable.getSpanStart(span);
        int spanEnd = editable.getSpanEnd(span);
        int spanFlag = editable.getSpanFlags(span);
        if (spanStart < cursorPos && spanEnd > cursorPos) {
            isLight = true;
        } else if (spanStart == cursorPos
                && (spanFlag == Spanned.SPAN_INCLUSIVE_INCLUSIVE || spanFlag == Spanned.SPAN_INCLUSIVE_EXCLUSIVE)) {
            isLight = true;
        } else if (spanEnd == cursorPos
                && (spanFlag == Spanned.SPAN_INCLUSIVE_INCLUSIVE || spanFlag == Spanned.SPAN_EXCLUSIVE_INCLUSIVE)) {
            isLight = true;
        }
    }

    return isLight;
}
 
Example 14
Source File: TokenCompleteTextView.java    From SocialTokenAutoComplete with Apache License 2.0 5 votes vote down vote up
public void onClick() {
    Editable text = getText();
    if (text == null) return;

    switch (tokenClickStyle) {
        case Select:
        case SelectDeselect:

            if (!view.isSelected()) {
                clearSelections();
                view.setSelected(true);
                break;
            }

            if (tokenClickStyle == TokenClickStyle.SelectDeselect) {
                view.setSelected(false);
                invalidate();
                break;
            }

            //If the view is already selected, we want to delete it
        case Delete:
            removeSpan(this);
            break;
        case None:
        default:
            if (getSelectionStart() != text.getSpanEnd(this) + 1) {
                //Make sure the selection is not in the middle of the span
                setSelection(text.getSpanEnd(this) + 1);
            }
    }
}
 
Example 15
Source File: ContactEditText.java    From material with Apache License 2.0 5 votes vote down vote up
private void replaceSpan(RecipientSpan span, Recipient newRecipient){
    Editable text = getText();
    int start = text.getSpanStart(span);
    int end = text.getSpanEnd(span);
    String replace = newRecipient.number;
    text.replace(start, end - 2, newRecipient.number, 0, replace.length());
    span.setRecipient(newRecipient);
    text.setSpan(span, start, start + replace.length() + 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
 
Example 16
Source File: FixedURLSpan.java    From Pix-Art-Messenger with GNU General Public License v3.0 5 votes vote down vote up
public static void fix(final Editable editable) {
    for (final URLSpan urlspan : editable.getSpans(0, editable.length() - 1, URLSpan.class)) {
        final int start = editable.getSpanStart(urlspan);
        final int end = editable.getSpanEnd(urlspan);
        editable.removeSpan(urlspan);
        editable.setSpan(new FixedURLSpan(urlspan.getURL()), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    }
}
 
Example 17
Source File: TokenCompleteTextView.java    From TokenAutoComplete with Apache License 2.0 5 votes vote down vote up
@SuppressWarnings("WeakerAccess")
public void onClick() {
    Editable text = getText();
    if (text == null) return;

    switch (tokenClickStyle) {
        case Select:
        case SelectDeselect:

            if (!view.isSelected()) {
                clearSelections();
                view.setSelected(true);
                break;
            }

            if (tokenClickStyle == TokenClickStyle.SelectDeselect || !isTokenRemovable(token)) {
                view.setSelected(false);
                invalidate();
                break;
            }
            //If the view is already selected, we want to delete it
        case Delete:
            if (isTokenRemovable(token)) {
                removeSpan(text, this);
            }
            break;
        case None:
        default:
            if (getSelectionStart() != text.getSpanEnd(this)) {
                //Make sure the selection is not in the middle of the span
                setSelection(text.getSpanEnd(this));
            }
    }
}
 
Example 18
Source File: SpellChecker.java    From android_9.0.0_r45 with Apache License 2.0 4 votes vote down vote up
private void spellCheck() {
    if (mSpellCheckerSession == null) return;

    Editable editable = (Editable) mTextView.getText();
    final int selectionStart = Selection.getSelectionStart(editable);
    final int selectionEnd = Selection.getSelectionEnd(editable);

    TextInfo[] textInfos = new TextInfo[mLength];
    int textInfosCount = 0;

    for (int i = 0; i < mLength; i++) {
        final SpellCheckSpan spellCheckSpan = mSpellCheckSpans[i];
        if (mIds[i] < 0 || spellCheckSpan.isSpellCheckInProgress()) continue;

        final int start = editable.getSpanStart(spellCheckSpan);
        final int end = editable.getSpanEnd(spellCheckSpan);

        // Do not check this word if the user is currently editing it
        final boolean isEditing;

        // Defer spell check when typing a word ending with a punctuation like an apostrophe
        // which could end up being a mid-word punctuation.
        if (selectionStart == end + 1
                && WordIterator.isMidWordPunctuation(
                        mCurrentLocale, Character.codePointBefore(editable, end + 1))) {
            isEditing = false;
        } else if (mIsSentenceSpellCheckSupported) {
            // Allow the overlap of the cursor and the first boundary of the spell check span
            // no to skip the spell check of the following word because the
            // following word will never be spell-checked even if the user finishes composing
            isEditing = selectionEnd <= start || selectionStart > end;
        } else {
            isEditing = selectionEnd < start || selectionStart > end;
        }
        if (start >= 0 && end > start && isEditing) {
            spellCheckSpan.setSpellCheckInProgress(true);
            final TextInfo textInfo = new TextInfo(editable, start, end, mCookie, mIds[i]);
            textInfos[textInfosCount++] = textInfo;
            if (DBG) {
                Log.d(TAG, "create TextInfo: (" + i + "/" + mLength + ") text = "
                        + textInfo.getSequence() + ", cookie = " + mCookie + ", seq = "
                        + mIds[i] + ", sel start = " + selectionStart + ", sel end = "
                        + selectionEnd + ", start = " + start + ", end = " + end);
            }
        }
    }

    if (textInfosCount > 0) {
        if (textInfosCount < textInfos.length) {
            TextInfo[] textInfosCopy = new TextInfo[textInfosCount];
            System.arraycopy(textInfos, 0, textInfosCopy, 0, textInfosCount);
            textInfos = textInfosCopy;
        }

        if (mIsSentenceSpellCheckSupported) {
            mSpellCheckerSession.getSentenceSuggestions(
                    textInfos, SuggestionSpan.SUGGESTIONS_MAX_SIZE);
        } else {
            mSpellCheckerSession.getSuggestions(textInfos, SuggestionSpan.SUGGESTIONS_MAX_SIZE,
                    false /* TODO Set sequentialWords to true for initial spell check */);
        }
    }
}
 
Example 19
Source File: MentionsEditText.java    From Spyglass with Apache License 2.0 4 votes vote down vote up
/**
 * Ensures that the text within each {@link MentionSpan} in the {@link Editable} correctly
 * matches what it should be outputting. If not, replace it with the correct value.
 *
 * @param text the {@link Editable} to examine
 */
private void ensureMentionSpanIntegrity(Editable text) {
    if (text == null) {
        return;
    }

    MentionSpan[] spans = text.getSpans(0, text.length(), MentionSpan.class);
    boolean spanAltered = false;
    for (MentionSpan span : spans) {
        int start = text.getSpanStart(span);
        int end = text.getSpanEnd(span);
        CharSequence spanText = text.subSequence(start, end).toString();
        Mentionable.MentionDisplayMode displayMode = span.getDisplayMode();

        switch (displayMode) {

            case PARTIAL:
            case FULL:
                String name = span.getDisplayString();
                if (!name.contentEquals(spanText) && start >= 0 && start < end && end <= text.length()) {
                    // Mention display name does not match what is being shown,
                    // replace text in span with proper display name
                    int cursor = getSelectionStart();
                    int diff = cursor - end;
                    text.removeSpan(span);
                    text.replace(start, end, name);
                    if (diff > 0 && start + end + diff < text.length()) {
                        text.replace(start + end, start + end + diff, "");
                    }
                    if (name.length() > 0) {
                        text.setSpan(span, start, start + name.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                    }
                    // Notify for partially deleted mentions.
                    if (mMentionWatchers.size() > 0 && displayMode == Mentionable.MentionDisplayMode.PARTIAL) {
                        notifyMentionPartiallyDeletedWatchers(span.getMention(), name, start, end);
                    }
                    spanAltered = true;
                }
                break;

            case NONE:
            default:
                // Mention with DisplayMode == NONE should be deleted from the text
                boolean hasListeners = mMentionWatchers.size() > 0;
                final String textBeforeDelete = hasListeners ? text.toString() : null;
                text.delete(start, end);
                setSelection(start);
                if (hasListeners) {
                    notifyMentionDeletedWatchers(span.getMention(), textBeforeDelete, start, end);
                }
                spanAltered = true;
                break;
        }
    }

    // Reset input method if spans have been changed (updates suggestions)
    if (spanAltered) {
        restartInput();
    }
}
 
Example 20
Source File: TokenCompleteTextView.java    From SocialTokenAutoComplete with Apache License 2.0 4 votes vote down vote up
private void updateHint() {
    Editable text = getText();
    CharSequence hintText = getHint();
    if (text == null || hintText == null) {
        return;
    }

    //Show hint if we need to
    if (prefix.length() > 0) {
        HintSpan[] hints = text.getSpans(0, text.length(), HintSpan.class);
        HintSpan hint = null;
        int testLength = prefix.length();
        if (hints.length > 0) {
            hint = hints[0];
            testLength += text.getSpanEnd(hint) - text.getSpanStart(hint);
        }

        if (text.length() == testLength) {
            hintVisible = true;

            if (hint != null) {
                return;//hint already visible
            }

            //We need to display the hint manually
            Typeface tf = getTypeface();
            int style = Typeface.NORMAL;
            if (tf != null) {
                style = tf.getStyle();
            }
            ColorStateList colors = getHintTextColors();

            HintSpan hintSpan = new HintSpan(null, style, (int)getTextSize(), colors, colors);
            text.insert(prefix.length(), hintText);
            text.setSpan(hintSpan, prefix.length(), prefix.length() + getHint().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            setSelection(prefix.length());

        } else {
            if (hint == null) {
                return; //hint already removed
            }

            //Remove the hint. There should only ever be one
            int sStart = text.getSpanStart(hint);
            int sEnd = text.getSpanEnd(hint);

            text.removeSpan(hint);
            text.replace(sStart, sEnd, "");

            hintVisible = false;
        }
    }
}