List of usage examples for android.text Spannable removeSpan
public void removeSpan(Object what);
From source file:com.hippo.nimingban.ui.ListActivity.java
private Spanned fixURLSpan(Spanned spanned) { Spannable spannable; if (spanned instanceof Spannable) { spannable = (Spannable) spanned; } else {// w w w .j a v a 2s. c o m spannable = new SpannableString(spanned); } URLSpan[] urlSpans = spannable.getSpans(0, spanned.length(), URLSpan.class); if (urlSpans == null) { return spanned; } for (URLSpan urlSpan : urlSpans) { String url = urlSpan.getURL(); if (TextUtils.isEmpty(url)) { spannable.removeSpan(urlSpan); } try { new URL(url); } catch (MalformedURLException e) { URL absoluteUrl; // It might be relative path try { // Use absolute url absoluteUrl = new URL(new URL(ACUrl.HOST), url); int start = spannable.getSpanStart(urlSpan); int end = spannable.getSpanEnd(urlSpan); spannable.removeSpan(urlSpan); spannable.setSpan(new URLSpan(absoluteUrl.toString()), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } catch (MalformedURLException e1) { // Can't get url spannable.removeSpan(urlSpan); } } } return spannable; }
From source file:org.proninyaroslav.libretorrent.fragments.DetailTorrentFragment.java
@Override public void onShow(final AlertDialog dialog) { if (dialog == null) { return;// w ww.ja v a 2 s . c o m } if (getFragmentManager().findFragmentByTag(TAG_ADD_TRACKERS_DIALOG) != null) { final TextInputEditText field = (TextInputEditText) dialog .findViewById(R.id.multiline_text_input_dialog); final TextInputLayout fieldLayout = (TextInputLayout) dialog .findViewById(R.id.layout_multiline_text_input_dialog); /* Dismiss error label if user has changed the text */ if (field != null && fieldLayout != null) { field.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { /* Nothing */ } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { fieldLayout.setErrorEnabled(false); fieldLayout.setError(null); /* Clear selection of invalid url */ Spannable text = field.getText(); ForegroundColorSpan[] errorSpans = text.getSpans(0, text.length(), ForegroundColorSpan.class); for (ForegroundColorSpan span : errorSpans) { text.removeSpan(span); } } @Override public void afterTextChanged(Editable s) { /* Nothing */ } }); } /* * It is necessary in order to the dialog is not closed by * pressing add/replace button if the text checker gave a false result */ Button addButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE); Button replaceButton = dialog.getButton(AlertDialog.BUTTON_NEGATIVE); addButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (field != null && fieldLayout != null) { String text = field.getText().toString(); List<String> urls = Arrays.asList(text.split(Utils.getLineSeparator())); if (checkEditTextField(urls, fieldLayout, field)) { addTrackersRequest(new ArrayList<>(urls), false); dialog.dismiss(); } } } }); replaceButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (field != null && fieldLayout != null) { String text = field.getText().toString(); List<String> urls = Arrays.asList(text.split(Utils.getLineSeparator())); if (checkEditTextField(urls, fieldLayout, field)) { addTrackersRequest(new ArrayList<>(urls), true); dialog.dismiss(); } } } }); /* Inserting links from the clipboard */ String clipboard = Utils.getClipboard(activity.getApplicationContext()); if (clipboard != null && field != null) { List<String> urls = Arrays.asList(clipboard.split(Utils.getLineSeparator())); ArrayList<String> validUrls = new ArrayList<>(); for (String url : urls) { if (Utils.isValidTrackerUrl(url)) { validUrls.add(url); } } field.setText(TextUtils.join(Utils.getLineSeparator(), validUrls)); } } else if (getFragmentManager().findFragmentByTag(TAG_SPEED_LIMIT_DIALOG) != null) { TextInputEditText upload = (TextInputEditText) dialog.findViewById(R.id.upload_limit); TextInputEditText download = (TextInputEditText) dialog.findViewById(R.id.download_limit); if (upload != null && download != null) { int minSpeedLimit = 0; int maxSpeedLimit = Integer.MAX_VALUE; InputFilter[] filter = new InputFilter[] { new InputFilterMinMax(minSpeedLimit, maxSpeedLimit) }; upload.setFilters(filter); if (TextUtils.isEmpty(upload.getText())) { upload.setText((uploadSpeedLimit != -1 ? Integer.toString(uploadSpeedLimit / 1024) : Integer.toString(minSpeedLimit))); } download.setFilters(filter); if (TextUtils.isEmpty(download.getText())) { download.setText((downloadSpeedLimit != -1 ? Integer.toString(downloadSpeedLimit / 1024) : Integer.toString(minSpeedLimit))); } } } }
From source file:com.tct.mail.browse.MessageHeaderView.java
private void stripUnderlines(TextView textView, Account account) { final Spannable spannable = (Spannable) textView.getText(); final URLSpan[] urls = textView.getUrls(); for (URLSpan span : urls) { final int start = spannable.getSpanStart(span); final int end = spannable.getSpanEnd(span); spannable.removeSpan(span); //TS: rong-tang 2016-04-19 EMAIL BUGFIX-1951808 MOD_S span = new EmailAddressSpan(getContext(), account, span.getURL().substring(7), mContactInfoSource); ((EmailAddressSpan) span).setFragmentManager(mFragmentManager); //TS: rong-tang 2016-04-19 EMAIL BUGFIX-1951808 MOD_E spannable.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); }/*w ww. j av a 2 s . c om*/ }
From source file:android.support.text.emoji.EmojiProcessor.java
/** * Checks a given CharSequence for emojis, and adds EmojiSpans if any emojis are found. * <p>//from w w w . j a va 2 s .c o m * <ul> * <li>If no emojis are found, {@code charSequence} given as the input is returned without * any changes. i.e. charSequence is a String, and no emojis are found, the same String is * returned.</li> * <li>If the given input is not a Spannable (such as String), and at least one emoji is found * a new {@link android.text.Spannable} instance is returned. </li> * <li>If the given input is a Spannable, the same instance is returned. </li> * </ul> * * @param charSequence CharSequence to add the EmojiSpans, cannot be {@code null} * @param start start index in the charSequence to look for emojis, should be greater than or * equal to {@code 0}, also less than {@code charSequence.length()} * @param end end index in the charSequence to look for emojis, should be greater than or * equal to {@code start} parameter, also less than {@code charSequence.length()} * @param maxEmojiCount maximum number of emojis in the {@code charSequence}, should be greater * than or equal to {@code 0} * @param replaceAll whether to replace all emoji with {@link EmojiSpan}s */ CharSequence process(@NonNull final CharSequence charSequence, @IntRange(from = 0) int start, @IntRange(from = 0) int end, @IntRange(from = 0) int maxEmojiCount, final boolean replaceAll) { final boolean isSpannableBuilder = charSequence instanceof SpannableBuilder; if (isSpannableBuilder) { ((SpannableBuilder) charSequence).beginBatchEdit(); } try { Spannable spannable = null; // if it is a spannable already, use the same instance to add/remove EmojiSpans. // otherwise wait until the the first EmojiSpan found in order to change the result // into a Spannable. if (isSpannableBuilder || charSequence instanceof Spannable) { spannable = (Spannable) charSequence; } if (spannable != null) { final EmojiSpan[] spans = spannable.getSpans(start, end, EmojiSpan.class); if (spans != null && spans.length > 0) { // remove existing spans, and realign the start, end according to spans // if start or end is in the middle of an emoji they should be aligned final int length = spans.length; for (int index = 0; index < length; index++) { final EmojiSpan span = spans[index]; final int spanStart = spannable.getSpanStart(span); final int spanEnd = spannable.getSpanEnd(span); // Remove span only when its spanStart is NOT equal to current end. // During add operation an emoji at index 0 is added with 0-1 as start and // end indices. Therefore if there are emoji spans at [0-1] and [1-2] // and end is 1, the span between 0-1 should be deleted, not 1-2. if (spanStart != end) { spannable.removeSpan(span); } start = Math.min(spanStart, start); end = Math.max(spanEnd, end); } } } if (start == end || start >= charSequence.length()) { return charSequence; } // calculate max number of emojis that can be added. since getSpans call is a relatively // expensive operation, do it only when maxEmojiCount is not unlimited. if (maxEmojiCount != EmojiCompat.EMOJI_COUNT_UNLIMITED && spannable != null) { maxEmojiCount -= spannable.getSpans(0, spannable.length(), EmojiSpan.class).length; } // add new ones int addedCount = 0; final ProcessorSm sm = new ProcessorSm(mMetadataRepo.getRootNode()); int currentOffset = start; int codePoint = Character.codePointAt(charSequence, currentOffset); while (currentOffset < end && addedCount < maxEmojiCount) { final int action = sm.check(codePoint); switch (action) { case ACTION_ADVANCE_BOTH: start += Character.charCount(Character.codePointAt(charSequence, start)); currentOffset = start; if (currentOffset < end) { codePoint = Character.codePointAt(charSequence, currentOffset); } break; case ACTION_ADVANCE_END: currentOffset += Character.charCount(codePoint); if (currentOffset < end) { codePoint = Character.codePointAt(charSequence, currentOffset); } break; case ACTION_FLUSH: if (replaceAll || !hasGlyph(charSequence, start, currentOffset, sm.getFlushMetadata())) { if (spannable == null) { spannable = new SpannableString(charSequence); } addEmoji(spannable, sm.getFlushMetadata(), start, currentOffset); addedCount++; } start = currentOffset; break; } } // After the last codepoint is consumed the state machine might be in a state where it // identified an emoji before. i.e. abc[women-emoji] when the last codepoint is consumed // state machine is waiting to see if there is an emoji sequence (i.e. ZWJ). // Need to check if it is in such a state. if (sm.isInFlushableState() && addedCount < maxEmojiCount) { if (replaceAll || !hasGlyph(charSequence, start, currentOffset, sm.getCurrentMetadata())) { if (spannable == null) { spannable = new SpannableString(charSequence); } addEmoji(spannable, sm.getCurrentMetadata(), start, currentOffset); addedCount++; } } return spannable == null ? charSequence : spannable; } finally { if (isSpannableBuilder) { ((SpannableBuilder) charSequence).endBatchEdit(); } } }
From source file:com.android.ex.chips.RecipientEditTextView.java
/** * Replace the more chip, if it exists, with all of the recipient chips it had replaced when the * RecipientEditTextView gains focus./*from ww w .java2 s. c om*/ */ // Visible for testing. /* package */void removeMoreChip() { if (mMoreChip != null) { final Spannable span = getSpannable(); span.removeSpan(mMoreChip); mMoreChip = null; // Re-add the spans that were removed. if (mRemovedSpans != null && mRemovedSpans.size() > 0) { // Recreate each removed span. final DrawableRecipientChip[] recipients = getSortedRecipients(); // Start the search for tokens after the last currently visible // chip. if (recipients == null || recipients.length == 0) return; int end = span.getSpanEnd(recipients[recipients.length - 1]); final Editable editable = getText(); for (final DrawableRecipientChip chip : mRemovedSpans) { int chipStart; int chipEnd; String token; // Need to find the location of the chip, again. token = (String) chip.getOriginalText(); // As we find the matching recipient for the remove spans, // reduce the size of the string we need to search. // That way, if there are duplicates, we always find the correct // recipient. chipStart = editable.toString().indexOf(token, end); end = chipEnd = Math.min(editable.length(), chipStart + token.length()); // Only set the span if we found a matching token. if (chipStart != -1) editable.setSpan(chip, chipStart, chipEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } mRemovedSpans.clear(); } } }
From source file:com.android.ex.chips.RecipientEditTextView.java
/** * Show specified chip as selected. If the RecipientChip is just an email address, selecting the chip will take the * contents of the chip and place it at the end of the RecipientEditTextView for inline editing. If the * RecipientChip is a complete contact, then selecting the chip will change the background color of the chip, show * the delete icon, and a popup window with the address in use highlighted and any other alternate addresses for the * contact./* www. j ava 2s. c o m*/ * * @param currentChip * Chip to select. * @return A RecipientChip in the selected state or null if the chip just contained an email address. */ private DrawableRecipientChip selectChip(final DrawableRecipientChip currentChip) { if (shouldShowEditableText(currentChip)) { final CharSequence text = currentChip.getValue(); final Editable editable = getText(); final Spannable spannable = getSpannable(); final int spanStart = spannable.getSpanStart(currentChip); final int spanEnd = spannable.getSpanEnd(currentChip); spannable.removeSpan(currentChip); editable.delete(spanStart, spanEnd); setCursorVisible(true); setSelection(editable.length()); editable.append(text); return constructChipSpan(RecipientEntry.constructFakeEntry((String) text, isValid(text.toString())), true, false); } else if (currentChip.getContactId() == RecipientEntry.GENERATED_CONTACT || currentChip.isGalContact()) { final int start = getChipStart(currentChip); final int end = getChipEnd(currentChip); getSpannable().removeSpan(currentChip); DrawableRecipientChip newChip; try { if (mNoChips) return null; newChip = constructChipSpan(currentChip.getEntry(), true, false); } catch (final NullPointerException e) { Log.e(TAG, e.getMessage(), e); return null; } final Editable editable = getText(); QwertyKeyListener.markAsReplaced(editable, start, end, ""); if (start == -1 || end == -1) Log.d(TAG, "The chip being selected no longer exists but should."); else editable.setSpan(newChip, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); newChip.setSelected(true); if (shouldShowEditableText(newChip)) scrollLineIntoView(getLayout().getLineForOffset(getChipStart(newChip))); //showAddress(newChip,mAddressPopup,getWidth()); setCursorVisible(false); return newChip; } else { final int start = getChipStart(currentChip); final int end = getChipEnd(currentChip); getSpannable().removeSpan(currentChip); DrawableRecipientChip newChip; try { newChip = constructChipSpan(currentChip.getEntry(), true, false); } catch (final NullPointerException e) { Log.e(TAG, e.getMessage(), e); return null; } final Editable editable = getText(); QwertyKeyListener.markAsReplaced(editable, start, end, ""); if (start == -1 || end == -1) Log.d(TAG, "The chip being selected no longer exists but should."); else editable.setSpan(newChip, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); newChip.setSelected(true); if (shouldShowEditableText(newChip)) scrollLineIntoView(getLayout().getLineForOffset(getChipStart(newChip))); //showAlternates(newChip,mAlternatesPopup,getWidth()); setCursorVisible(false); return newChip; } }
From source file:com.android.ex.chips.RecipientEditTextView.java
/** * Remove the chip and any text associated with it from the RecipientEditTextView. * * @param alsoNotifyAboutDataChanges/*from w ww. j av a2s . c om*/ */ // Visible for testing. /* package */void removeChip(final DrawableRecipientChip chip, final boolean alsoNotifyAboutDataChanges) { if (!alsoNotifyAboutDataChanges) --mPreviousChipsCount; final Spannable spannable = getSpannable(); final int spanStart = spannable.getSpanStart(chip); final int spanEnd = spannable.getSpanEnd(chip); final Editable text = getText(); int toDelete = spanEnd; final boolean wasSelected = chip == mSelectedChip; // Clear that there is a selected chip before updating any text. if (wasSelected) mSelectedChip = null; // Always remove trailing spaces when removing a chip. while (toDelete >= 0 && toDelete < text.length() && text.charAt(toDelete) == ' ') toDelete++; spannable.removeSpan(chip); if (spanStart >= 0 && toDelete > 0) text.delete(spanStart, toDelete); if (wasSelected) clearSelectedChip(); }
From source file:com.android.ex.chips.RecipientEditTextView.java
/** * Create the more chip. The more chip is text that replaces any chips that do not fit in the pre-defined available * space when the RecipientEditTextView loses focus. *//*from ww w . ja v a 2 s . c o m*/ // Visible for testing. /* package */void createMoreChip() { if (mNoChips) { createMoreChipPlainText(); return; } if (!mShouldShrink) return; final ImageSpan[] tempMore = getSpannable().getSpans(0, getText().length(), MoreImageSpan.class); if (tempMore.length > 0) getSpannable().removeSpan(tempMore[0]); final DrawableRecipientChip[] recipients = getSortedRecipients(); if (recipients == null || recipients.length <= CHIP_LIMIT) { mMoreChip = null; return; } final Spannable spannable = getSpannable(); final int numRecipients = recipients.length; final int overage = numRecipients - CHIP_LIMIT; final MoreImageSpan moreSpan = createMoreSpan(overage); mRemovedSpans = new ArrayList<DrawableRecipientChip>(); int totalReplaceStart = 0; int totalReplaceEnd = 0; final Editable text = getText(); for (int i = numRecipients - overage; i < recipients.length; i++) { mRemovedSpans.add(recipients[i]); if (i == numRecipients - overage) totalReplaceStart = spannable.getSpanStart(recipients[i]); if (i == recipients.length - 1) totalReplaceEnd = spannable.getSpanEnd(recipients[i]); if (mTemporaryRecipients == null || !mTemporaryRecipients.contains(recipients[i])) { final int spanStart = spannable.getSpanStart(recipients[i]); final int spanEnd = spannable.getSpanEnd(recipients[i]); recipients[i].setOriginalText(text.toString().substring(spanStart, spanEnd)); } spannable.removeSpan(recipients[i]); } if (totalReplaceEnd < text.length()) totalReplaceEnd = text.length(); final int end = Math.max(totalReplaceStart, totalReplaceEnd); final int start = Math.min(totalReplaceStart, totalReplaceEnd); final SpannableString chipText = new SpannableString(text.subSequence(start, end)); chipText.setSpan(moreSpan, 0, chipText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); text.replace(start, end, chipText); mMoreChip = moreSpan; // If adding the +more chip goes over the limit, resize accordingly. if (!isPhoneQuery() && getLineCount() > mMaxLines) setMaxLines(getLineCount()); }