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

The following examples show how to use android.text.Spannable#subSequence() . 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: CharPolicy.java    From Autocomplete with Apache License 2.0 6 votes vote down vote up
@NonNull
@Override
public CharSequence getQuery(@NonNull Spannable text) {
    QuerySpan[] span = text.getSpans(0, text.length(), QuerySpan.class);
    if (span == null || span.length == 0) {
        // Should never happen.
        log("getQuery: there's no span!");
        return "";
    }
    log("getQuery: found spans: "+span.length);
    QuerySpan sp = span[0];
    log("getQuery: span start is "+text.getSpanStart(sp));
    log("getQuery: span end is "+text.getSpanEnd(sp));
    CharSequence seq =  text.subSequence(text.getSpanStart(sp), text.getSpanEnd(sp));
    log("getQuery: returning "+seq);
    return seq;
}
 
Example 2
Source File: RuleSpannables.java    From talkback with Apache License 2.0 6 votes vote down vote up
/** Creates a menu item for ClickableSpan. */
private @Nullable ContextMenuItem createMenuItemForClickableSpan(
    Context context,
    ContextMenuItemBuilder menuItemBuilder,
    int itemId,
    Spannable spannable,
    ClickableSpan clickableSpan) {
  final int start = spannable.getSpanStart(clickableSpan);
  final int end = spannable.getSpanEnd(clickableSpan);
  if (start < 0 || end < 0) {
    return null;
  }
  final CharSequence label = spannable.subSequence(start, end);
  if (TextUtils.isEmpty(label)) {
    return null;
  }

  SpannableUtils.stripTargetSpanFromText(label, TARGET_SPAN_CLASS);
  final ContextMenuItem item =
      menuItemBuilder.createMenuItem(context, R.id.group_links, itemId, Menu.NONE, label);
  item.setOnMenuItemClickListener(new ClickableSpanMenuItemClickListener(clickableSpan));
  return item;
}
 
Example 3
Source File: StylingHelper.java    From Pix-Art-Messenger with GNU General Public License v3.0 6 votes vote down vote up
static CharSequence subSequence(CharSequence charSequence, int start, int end) {
    if (start == 0 && charSequence.length() + 1 == end) {
        return charSequence;
    }
    if (charSequence instanceof Spannable) {
        Spannable spannable = (Spannable) charSequence;
        Spannable sub = (Spannable) spannable.subSequence(start, end);
        for (Class<? extends ParcelableSpan> clazz : SPAN_CLASSES) {
            ParcelableSpan[] spannables = spannable.getSpans(start, end, clazz);
            for (ParcelableSpan parcelableSpan : spannables) {
                int beginSpan = spannable.getSpanStart(parcelableSpan);
                int endSpan = spannable.getSpanEnd(parcelableSpan);
                if (beginSpan >= start && endSpan <= end) {
                    continue;
                }
                sub.setSpan(clone(parcelableSpan), Math.max(beginSpan - start, 0), Math.min(sub.length() - 1, endSpan), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
        }
        return sub;
    } else {
        return charSequence.subSequence(start, end);
    }
}
 
Example 4
Source File: Utils.java    From Android-RecurrencePicker with Apache License 2.0 6 votes vote down vote up
/**
 * Determines whether a new span at [start,end) will overlap with any existing span.
 */
private static boolean spanWillOverlap(Spannable spanText, URLSpan[] spanList, int start,
                                       int end) {
    if (start == end) {
        // empty span, ignore
        return false;
    }
    for (URLSpan span : spanList) {
        int existingStart = spanText.getSpanStart(span);
        int existingEnd = spanText.getSpanEnd(span);
        if ((start >= existingStart && start < existingEnd) ||
                end > existingStart && end <= existingEnd) {
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                CharSequence seq = spanText.subSequence(start, end);
                Log.v(TAG, "Not linkifying " + seq + " as phone number due to overlap");
            }
            return true;
        }
    }

    return false;
}
 
Example 5
Source File: StylingHelper.java    From Conversations with GNU General Public License v3.0 6 votes vote down vote up
static CharSequence subSequence(CharSequence charSequence, int start, int end) {
	if (start == 0 && charSequence.length() + 1 == end) {
		return charSequence;
	}
	if (charSequence instanceof Spannable) {
		Spannable spannable = (Spannable) charSequence;
		Spannable sub = (Spannable) spannable.subSequence(start, end);
		for (Class<? extends ParcelableSpan> clazz : SPAN_CLASSES) {
			ParcelableSpan[] spannables = spannable.getSpans(start, end, clazz);
			for (ParcelableSpan parcelableSpan : spannables) {
				int beginSpan = spannable.getSpanStart(parcelableSpan);
				int endSpan = spannable.getSpanEnd(parcelableSpan);
				if (beginSpan >= start && endSpan <= end) {
					continue;
				}
				sub.setSpan(clone(parcelableSpan), Math.max(beginSpan - start, 0), Math.min(sub.length() - 1, endSpan), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
			}
		}
		return sub;
	} else {
		return charSequence.subSequence(start, end);
	}
}
 
Example 6
Source File: SocialViewHelper.java    From socialview with Apache License 2.0 5 votes vote down vote up
private static void spanAll(Spannable spannable, Pattern pattern, Supplier<CharacterStyle> styleSupplier) {
    final Matcher matcher = pattern.matcher(spannable);
    while (matcher.find()) {
        final int start = matcher.start();
        final int end = matcher.end();
        final Object span = styleSupplier.get();
        spannable.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        if (span instanceof SocialClickableSpan) {
            ((SocialClickableSpan) span).text = spannable.subSequence(start, end);
        }
    }
}
 
Example 7
Source File: RuleSpannables.java    From talkback with Apache License 2.0 5 votes vote down vote up
/**
 * Creates a menu item for URLSpan. <strong>Note: </strong> This method will not create menu item
 * for relative URLs.
 */
private @Nullable ContextMenuItem createMenuItemForUrlSpan(
    Context context,
    ContextMenuItemBuilder menuItemBuilder,
    int itemId,
    Spannable spannable,
    URLSpan span) {
  final String url = span.getURL();
  final int start = spannable.getSpanStart(span);
  final int end = spannable.getSpanEnd(span);
  if (start < 0 || end < 0) {
    return null;
  }
  final CharSequence label = spannable.subSequence(start, end);
  if (TextUtils.isEmpty(url) || TextUtils.isEmpty(label)) {
    return null;
  }

  final Uri uri = Uri.parse(url);
  if (uri.isRelative()) {
    // Generally, only absolute URIs are resolvable to an activity
    return null;
  }

  // Strip out ClickableSpans/UrlSpans from the label text.
  // A11y framework has changed how it handles double-tap from O. It's possible that double-tap
  // on the menu item will invoke ClickableSpans in the label text instead of calling
  // MenuItemClickListener. Thus we should remove ClickableSpans from label text.
  // Also apply this rule to pre-O in order to have consistent text appearance.
  SpannableUtils.stripTargetSpanFromText(label, TARGET_SPAN_CLASS);
  final ContextMenuItem item =
      menuItemBuilder.createMenuItem(context, R.id.group_links, itemId, Menu.NONE, label);
  item.setOnMenuItemClickListener(new UrlSpanMenuItemClickListener(context, uri));
  return item;
}
 
Example 8
Source File: Linkify.java    From android_9.0.0_r45 with Apache License 2.0 4 votes vote down vote up
private static Future<Void> addLinksAsync(
        @NonNull Spannable text,
        @NonNull TextClassifier classifier,
        @Nullable TextLinksParams params,
        @Nullable Executor executor,
        @Nullable Consumer<Integer> callback,
        @Nullable Runnable modifyTextView) {
    Preconditions.checkNotNull(text);
    Preconditions.checkNotNull(classifier);

    // TODO: This is a bug. We shouldnot call getMaxGenerateLinksTextLength() on the UI thread.
    // The input text may exceed the maximum length the text classifier can handle. In such
    // cases, we process the text up to the maximum length.
    final CharSequence truncatedText = text.subSequence(
            0, Math.min(text.length(), classifier.getMaxGenerateLinksTextLength()));

    final TextClassifier.EntityConfig entityConfig = (params == null)
            ? null : params.getEntityConfig();
    final TextLinks.Request request = new TextLinks.Request.Builder(truncatedText)
            .setLegacyFallback(true)
            .setEntityConfig(entityConfig)
            .build();
    final Supplier<TextLinks> supplier = () -> classifier.generateLinks(request);
    final Consumer<TextLinks> consumer = links -> {
        if (links.getLinks().isEmpty()) {
            if (callback != null) {
                callback.accept(TextLinks.STATUS_NO_LINKS_FOUND);
            }
            return;
        }

        // Remove spans only for the part of the text we generated links for.
        final TextLinkSpan[] old =
                text.getSpans(0, truncatedText.length(), TextLinkSpan.class);
        for (int i = old.length - 1; i >= 0; i--) {
            text.removeSpan(old[i]);
        }

        final @TextLinks.Status int result = params.apply(text, links);
        if (result == TextLinks.STATUS_LINKS_APPLIED) {
            if (modifyTextView != null) {
                modifyTextView.run();
            }
        }
        if (callback != null) {
            callback.accept(result);
        }
    };
    if (executor == null) {
        return CompletableFuture.supplyAsync(supplier).thenAccept(consumer);
    } else {
        return CompletableFuture.supplyAsync(supplier, executor).thenAccept(consumer);
    }
}
 
Example 9
Source File: FeedbackProcessingUtils.java    From talkback with Apache License 2.0 4 votes vote down vote up
/**
 * Splits and adds feedback to {@link FeedbackItem}s for spannable text contained within this
 * {@link FeedbackItem}
 *
 * @param item The item to process for formatted text.
 */
public static void addFormattingCharacteristics(FeedbackItem item) {
  for (int i = 0; i < item.getFragments().size(); ++i) {
    final FeedbackFragment fragment = item.getFragments().get(i);
    final CharSequence fragmentText = fragment.getText();
    if (TextUtils.isEmpty(fragmentText) || !(fragmentText instanceof Spannable)) {
      continue;
    }

    Spannable spannable = (Spannable) fragmentText;

    int len = spannable.length();
    int next;
    boolean isFirstFragment = true;
    for (int begin = 0; begin < len; begin = next) {
      next = nextSpanTransition(spannable, begin, len, LocaleSpan.class, TARGET_SPAN_CLASS);

      // CharacterStyle is a superclass of both ClickableSpan(including URLSpan) and LocaleSpan;
      // we want to split by only ClickableSpan and LocaleSpan, but it is OK if we request any
      // CharacterStyle in the list of spans since we ignore the ones that are not
      // ClickableSpan/LocaleSpan.
      CharacterStyle[] spans = spannable.getSpans(begin, next, CharacterStyle.class);
      CharacterStyle chosenSpan = null;
      for (CharacterStyle span : spans) {
        if (span instanceof LocaleSpan) {
          // Prioritize LocaleSpan, quit the loop when a LocaleSpan is detected. Note: If multiple
          // LocaleSpans are attached to the text, first LocaleSpan is given preference.
          chosenSpan = span;
          break;
        } else if ((span instanceof ClickableSpan) || (span instanceof URLSpan)) {
          chosenSpan = span;
        }
        // Ignore other CharacterStyle.
      }
      final FeedbackFragment newFragment;
      CharSequence subString = spannable.subSequence(begin, next);
      boolean isIdentifier =
          SpannableUtils.isWrappedWithTargetSpan(
              subString, SpannableUtils.IdentifierSpan.class, /* shouldTrim= */ true);
      if (isIdentifier) {
        continue;
      }
      if (isFirstFragment) {
        // This is the first new fragment, so we should reuse the old fragment.
        // That way, we'll keep the existing haptic/earcon feedback at the beginning!
        isFirstFragment = false;
        newFragment = fragment;
        newFragment.setText(subString);
      } else {
        // Otherwise, add after the last fragment processed/added.
        newFragment = new FeedbackFragment(subString, /* speechParams= */ null);
        ++i;
        newFragment.setStartIndexInFeedbackItem(begin);
        item.addFragmentAtPosition(newFragment, i);
      }
      if (chosenSpan instanceof LocaleSpan) { // LocaleSpan
        newFragment.setLocale(((LocaleSpan) chosenSpan).getLocale());
      } else if (chosenSpan != null) { // ClickableSpan (including UrlSpan)
        handleClickableSpan(newFragment);
      }
    }
  }
}