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

The following examples show how to use android.text.Spanned#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: ClonedSpannableString.java    From memoir with Apache License 2.0 6 votes vote down vote up
private void init(CharSequence source, int start, int end) {
    int initial = 20;
    mSpans = new Object[initial];
    mSpanData = new int[initial * 3];

    if (source instanceof Spanned) {
        Spanned sp = (Spanned) source;
        for (Object span : sp.getSpans(start, end, Object.class)) {
            if (span instanceof CharacterStyle || span instanceof ParagraphStyle) {
                int st = sp.getSpanStart(span);
                int en = sp.getSpanEnd(span);
                int fl = sp.getSpanFlags(span);

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

                setSpan(span, st - start, en - start, fl);
            }
        }
    }
}
 
Example 2
Source File: ConverterSpannedToHtml.java    From memoir with Apache License 2.0 6 votes vote down vote up
/**
 * Convert a spanned text within a paragraph
 */
private void withinParagraph(final Spanned text, int start, int end) {
    // create sorted set of CharacterStyles
    SortedSet<CharacterStyle> sortedSpans = new TreeSet<>(new Comparator<CharacterStyle>() {
        @Override
        public int compare(CharacterStyle s1, CharacterStyle s2) {
            int start1 = text.getSpanStart(s1);
            int start2 = text.getSpanStart(s2);
            if (start1 != start2)
                return start1 - start2;        // span which starts first comes first

            int end1 = text.getSpanEnd(s1);
            int end2 = text.getSpanEnd(s2);
            if (end1 != end2) return end2 - end1;                // longer span comes first

            // if the paragraphs have the same span [start, end] we compare their name
            // compare the name only because local + anonymous classes have no canonical name
            return s1.getClass().getName().compareTo(s2.getClass().getName());
        }
    });
    List<CharacterStyle> spanList = Arrays.asList(text.getSpans(start, end, CharacterStyle.class));
    sortedSpans.addAll(spanList);

    // process paragraphs/divs
    convertText(text, start, end, sortedSpans);
}
 
Example 3
Source File: ConverterSpannedToHtml.java    From memoir with Apache License 2.0 6 votes vote down vote up
/**
 * Convert a spanned text within a paragraph
 */
private void withinParagraph(final Spanned text, int start, int end) {
    // create sorted set of CharacterStyles
    SortedSet<CharacterStyle> sortedSpans = new TreeSet<CharacterStyle>(new Comparator<CharacterStyle>() {
        @Override
        public int compare(CharacterStyle s1, CharacterStyle s2) {
            int start1 = text.getSpanStart(s1);
            int start2 = text.getSpanStart(s2);
            if (start1 != start2)
                return start1 - start2;        // span which starts first comes first

            int end1 = text.getSpanEnd(s1);
            int end2 = text.getSpanEnd(s2);
            if (end1 != end2) return end2 - end1;                // longer span comes first

            // if the paragraphs have the same span [start, end] we compare their name
            // compare the name only because local + anonymous classes have no canonical name
            return s1.getClass().getName().compareTo(s2.getClass().getName());
        }
    });
    List<CharacterStyle> spanList = Arrays.asList(text.getSpans(start, end, CharacterStyle.class));
    sortedSpans.addAll(spanList);

    // process paragraphs/divs
    convertText(text, start, end, sortedSpans);
}
 
Example 4
Source File: TextMeasureUtil.java    From FastTextView with Apache License 2.0 6 votes vote down vote up
/**
 * Do not support cross Span.
 *
 * @param text       text
 * @param parentSpan parentSpan
 * @param start      start index of parentSpan
 * @param end        end index of parentSpan
 * @param paint      TextPaint
 * @return recursive calculated width
 */
public int recursiveGetSizeWithReplacementSpan(CharSequence text, ReplacementSpan parentSpan, @IntRange(from = 0) int start, @IntRange(from = 0) int end, Paint paint) {
  if (text instanceof Spanned) {
    Spanned spannedText = (Spanned) text;
    List<ReplacementSpan> spans = getSortedReplacementSpans(spannedText, start, end);
    if (!spans.isEmpty()) {
      int lastIndexCursor = 0;
      int width = 0;
      for (ReplacementSpan span : spans) {
        if (span == parentSpan) {
          continue;
        }
        int spanStart = spannedText.getSpanStart(span);
        int spanEnd = spannedText.getSpanEnd(span);
        width += parentSpan.getSize(paint, text, lastIndexCursor, spanStart, null);
        width += span.getSize(paint, text, spanStart, spanEnd, null);
        lastIndexCursor = spanEnd;
      }
      if (lastIndexCursor < end) {
        width += parentSpan.getSize(paint, text, lastIndexCursor, end, null);
      }
      return width;
    }
  }
  return parentSpan.getSize(paint, text, start, end, null);
}
 
Example 5
Source File: ClonedSpannableString.java    From Android-RTEditor with Apache License 2.0 6 votes vote down vote up
private void init(CharSequence source, int start, int end) {
    int initial = 20;
    mSpans = new Object[initial];
    mSpanData = new int[initial * 3];

    if (source instanceof Spanned) {
        Spanned sp = (Spanned) source;
        for (Object span : sp.getSpans(start, end, Object.class)) {
            if (span instanceof CharacterStyle || span instanceof ParagraphStyle) {
                int st = sp.getSpanStart(span);
                int en = sp.getSpanEnd(span);
                int fl = sp.getSpanFlags(span);

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

                setSpan(span, st - start, en - start, fl);
            }
        }
    }
}
 
Example 6
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 7
Source File: ConverterSpannedToHtml.java    From memoir with Apache License 2.0 5 votes vote down vote up
private void convertText(Spanned text, int start, int end, SortedSet<CharacterStyle> spans) {
    while (start < end) {

        // get first CharacterStyle
        CharacterStyle span = spans.isEmpty() ? null : spans.first();
        int spanStart = span == null ? Integer.MAX_VALUE : text.getSpanStart(span);
        int spanEnd = span == null ? Integer.MAX_VALUE : text.getSpanEnd(span);

        if (start < spanStart) {

            // no paragraph, just plain text
            escape(text, start, Math.min(end, spanStart));
            start = spanStart;

        } else {

            // CharacterStyle found

            spans.remove(span);

            if (handleStartTag(span)) {
                convertText(text, Math.max(spanStart, start), Math.min(spanEnd, end), spans);
            }
            handleEndTag(span);

            start = spanEnd;
        }

    }
}
 
Example 8
Source File: ParseTreeResourceNode.java    From talkback with Apache License 2.0 5 votes vote down vote up
/**
 * Utility that copies spans from {@code fromSpan} to {@code toSpan}.
 *
 * @param toSpan Spannable that is supposed to contain fromSpan.
 * @param fromSpan Spannable that could contain spans that would be copied to toSpan.
 * @param toSpanStartIndex Starting index of occurrence fromSpan in toSpan.
 */
private static void copySpans(Spannable toSpan, Spanned fromSpan, int toSpanStartIndex) {
  if (toSpanStartIndex < 0 || toSpanStartIndex >= toSpan.length()) {
    LogUtils.e(
        TAG,
        "startIndex parameter (%d) is out of toSpan length %d",
        toSpanStartIndex,
        toSpan.length());
    return;
  }

  Object[] spans = fromSpan.getSpans(0, fromSpan.length(), Object.class);
  if (spans != null && spans.length > 0) {
    for (Object span : spans) {
      int spanStartIndex = fromSpan.getSpanStart(span);
      int spanEndIndex = fromSpan.getSpanEnd(span);
      if (spanStartIndex >= spanEndIndex) {
        continue;
      }
      int spanFlags = fromSpan.getSpanFlags(span);
      toSpan.setSpan(
          span,
          (toSpanStartIndex + spanStartIndex),
          (toSpanStartIndex + spanEndIndex),
          spanFlags);
    }
  }
}
 
Example 9
Source File: BetterLinkMovementExtended.java    From mvvm-template with GNU General Public License v3.0 5 votes vote down vote up
static BetterLinkMovementExtended.ClickableSpanWithText ofSpan(TextView textView, ClickableSpan span) {
    Spanned s = (Spanned) textView.getText();
    String text;
    if (span instanceof URLSpan) {
        text = ((URLSpan) span).getURL();
    } else {
        int start = s.getSpanStart(span);
        int end = s.getSpanEnd(span);
        text = s.subSequence(start, end).toString();
    }
    return new BetterLinkMovementExtended.ClickableSpanWithText(span, text);
}
 
Example 10
Source File: WordToSpan.java    From Android-WordToSpan with MIT License 5 votes vote down vote up
@Override
public void onClick(View textView) {
    Spanned s = (Spanned) tv.getText();
    int start = s.getSpanStart(this);
    int end = s.getSpanEnd(this);
    clickListener.onClick(type, s.subSequence(start, end).toString().trim());
}
 
Example 11
Source File: ConverterSpannedToHtml.java    From Android-RTEditor with Apache License 2.0 5 votes vote down vote up
private void convertText(Spanned text, int start, int end, SortedSet<CharacterStyle> spans) {
    while (start < end) {

        // get first CharacterStyle
        CharacterStyle span = spans.isEmpty() ? null : spans.first();
        int spanStart = span == null ? Integer.MAX_VALUE : text.getSpanStart(span);
        int spanEnd = span == null ? Integer.MAX_VALUE : text.getSpanEnd(span);

        if (start < spanStart) {

            // no paragraph, just plain text
            escape(text, start, Math.min(end, spanStart));
            start = spanStart;

        } else {

            // CharacterStyle found

            spans.remove(span);

            if (handleStartTag(span)) {
                convertText(text, Math.max(spanStart, start), Math.min(spanEnd, end), spans);
            }
            handleEndTag(span);

            start = spanEnd;
        }

    }
}
 
Example 12
Source File: OverlineSpan.java    From Dashchan with Apache License 2.0 5 votes vote down vote up
public static void draw(TextView textView, Canvas canvas) {
	Layout layout = textView.getLayout();
	if (layout != null) {
		CharSequence text = textView.getText();
		if (text instanceof Spanned) {
			Spanned spanned = (Spanned) text;
			OverlineSpan[] spans = spanned.getSpans(0, spanned.length(), OverlineSpan.class);
			if (spans != null && spans.length > 0) {
				int paddingTop = textView.getTotalPaddingTop();
				int paddingLeft = textView.getPaddingLeft();
				int shift = (int) (textView.getTextSize() * 8f / 9f);
				float thickness = textView.getTextSize() / 15f - 0.25f;
				int color = textView.getCurrentTextColor();
				PAINT.setColor(color);
				PAINT.setStrokeWidth(thickness);
				for (OverlineSpan span : spans) {
					int start = spanned.getSpanStart(span);
					int end = spanned.getSpanEnd(span);
					int lineStart = layout.getLineForOffset(start);
					int lineEnd = layout.getLineForOffset(end);
					for (int i = lineStart; i <= lineEnd; i++) {
						float left = i == lineStart ? layout.getPrimaryHorizontal(start) : layout.getLineLeft(i);
						float right = i == lineEnd ? layout.getPrimaryHorizontal(end) : layout.getLineRight(i);
						float top = layout.getLineBaseline(i) - shift + 0.5f;
						canvas.drawLine(paddingLeft + left, paddingTop + top, paddingLeft + right,
								paddingTop + top, PAINT);
					}
				}
			}
		}
	}
}
 
Example 13
Source File: ComposedFrame.java    From Tehreer-Android with Apache License 2.0 5 votes vote down vote up
private void drawBackground(@NonNull Canvas canvas) {
    int frameLeft = 0;
    int frameRight = (int) (mWidth + 0.5f);

    int lineCount = lineList.size();
    for (int i = 0; i < lineCount; i++) {
        ComposedLine composedLine = lineList.get(i);
        Object[] lineSpans = composedLine.getSpans();

        for (Object style : lineSpans) {
            if (style instanceof LineBackgroundSpan) {
                LineBackgroundSpan span = (LineBackgroundSpan) style;

                Spanned sourceText = (Spanned) source;
                int spanStart = sourceText.getSpanStart(span);
                int spanEnd = sourceText.getSpanEnd(span);

                int lineStart = composedLine.getCharStart();
                int lineEnd = composedLine.getCharEnd();
                if (lineStart >= spanEnd || lineEnd <= spanStart) {
                    continue;
                }

                Paint paint = lazyPaint();
                int lineTop = (int) (composedLine.getTop() + 0.5f);
                int lineBaseline = (int) (composedLine.getOriginY() + 0.5f);
                int lineBottom = (int) (composedLine.getTop() + composedLine.getHeight() + 0.5f);

                span.drawBackground(canvas, paint, frameLeft, frameRight,
                                    lineTop, lineBaseline, lineBottom,
                                    sourceText, lineStart, lineEnd, i);
            }
        }
    }
}
 
Example 14
Source File: CustomClickableSpan.java    From SimplifySpan with MIT License 5 votes vote down vote up
@Override
public void onClick(View widget) {
    if (null != mOnClickableSpanListener) {
        TextView tv = (TextView) widget;
        Spanned spanned = (Spanned) tv.getText();
        mStartSpanIndex = spanned.getSpanStart(this);
        mEndSpanIndex = spanned.getSpanEnd(this);
        mClickText = spanned.subSequence(mStartSpanIndex, mEndSpanIndex).toString();
        mOnClickableSpanListener.onClick(tv, this);
    }
}
 
Example 15
Source File: PasswordTransformationMethod.java    From android_9.0.0_r45 with Apache License 2.0 5 votes vote down vote up
public char charAt(int i) {
    if (mSource instanceof Spanned) {
        Spanned sp = (Spanned) mSource;

        int st = sp.getSpanStart(TextKeyListener.ACTIVE);
        int en = sp.getSpanEnd(TextKeyListener.ACTIVE);

        if (i >= st && i < en) {
            return mSource.charAt(i);
        }

        Visible[] visible = sp.getSpans(0, sp.length(), Visible.class);

        for (int a = 0; a < visible.length; a++) {
            if (sp.getSpanStart(visible[a].mTransformer) >= 0) {
                st = sp.getSpanStart(visible[a]);
                en = sp.getSpanEnd(visible[a]);

                if (i >= st && i < en) {
                    return mSource.charAt(i);
                }
            }
        }
    }

    return DOT;
}
 
Example 16
Source File: RecipientsEditor.java    From mollyim-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 17
Source File: SpannableStringBuilder.java    From JotaTextEditor with Apache License 2.0 4 votes vote down vote up
/**
 * Create a new SpannableStringBuilder containing a copy of the
 * specified slice of the specified text, including its spans if any.
 */
public SpannableStringBuilder(CharSequence text, int start, int end) {
    int srclen = end - start;

    int len = ArrayUtils.idealCharArraySize(srclen + 1);
    mText = new char[len];
    mGapStart = srclen;
    mGapLength = len - srclen;

    TextUtils.getChars(text, start, end, mText, 0);

    mSpanCount = 0;
    int alloc = ArrayUtils.idealIntArraySize(0);
    mSpans = new Object[alloc];
    mSpanStarts = new int[alloc];
    mSpanEnds = new int[alloc];
    mSpanFlags = new int[alloc];

    if (text instanceof Spanned) {
        Spanned sp = (Spanned) text;
        Object[] spans = sp.getSpans(start, end, Object.class);

        for (int i = 0; i < spans.length; i++) {
            if (spans[i] instanceof NoCopySpan) {
                continue;
            }

            int st = sp.getSpanStart(spans[i]) - start;
            int en = sp.getSpanEnd(spans[i]) - start;
            int fl = sp.getSpanFlags(spans[i]);

            if (st < 0)
                st = 0;
            if (st > end - start)
                st = end - start;

            if (en < 0)
                en = 0;
            if (en > end - start)
                en = end - start;

            if ( st <= en ) {
                setSpan(spans[i], st, en, fl);
            }
        }
    }
}
 
Example 18
Source File: ReactTextView.java    From react-native-GPay with MIT License 4 votes vote down vote up
@Override
public int reactTagForTouch(float touchX, float touchY) {
  CharSequence text = getText();
  int target = getId();

  int x = (int) touchX;
  int y = (int) touchY;

  Layout layout = getLayout();
  if (layout == null) {
    // If the layout is null, the view hasn't been properly laid out yet. Therefore, we can't find
    // the exact text tag that has been touched, and the correct tag to return is the default one.
    return target;
  }
  int line = layout.getLineForVertical(y);

  int lineStartX = (int) layout.getLineLeft(line);
  int lineEndX = (int) layout.getLineRight(line);

  // TODO(5966918): Consider extending touchable area for text spans by some DP constant
  if (text instanceof Spanned && x >= lineStartX && x <= lineEndX) {
    Spanned spannedText = (Spanned) text;
    int index = layout.getOffsetForHorizontal(line, x);

    // We choose the most inner span (shortest) containing character at the given index
    // if no such span can be found we will send the textview's react id as a touch handler
    // In case when there are more than one spans with same length we choose the last one
    // from the spans[] array, since it correspond to the most inner react element
    ReactTagSpan[] spans = spannedText.getSpans(index, index, ReactTagSpan.class);

    if (spans != null) {
      int targetSpanTextLength = text.length();
      for (int i = 0; i < spans.length; i++) {
        int spanStart = spannedText.getSpanStart(spans[i]);
        int spanEnd = spannedText.getSpanEnd(spans[i]);
        if (spanEnd > index && (spanEnd - spanStart) <= targetSpanTextLength) {
          target = spans[i].getReactTag();
          targetSpanTextLength = (spanEnd - spanStart);
        }
      }
    }
  }

  return target;
}
 
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: SpannableUtils.java    From talkback with Apache License 2.0 4 votes vote down vote up
/**
 * Logs the type, position and args of spans which attach to given text, but only if log priority
 * is equal to Log.VERBOSE. Format is {type 'spanned text' extra-data} {type 'other text'
 * extra-data} ..."
 *
 * @param text Text to be logged
 */
public static String spansToStringForLogging(CharSequence text) {
  if (!LogUtils.shouldLog(Log.VERBOSE)) {
    return null;
  }

  if (isEmptyOrNotSpannableStringType(text)) {
    return null;
  }

  Spanned spanned = (Spanned) text;
  ParcelableSpan[] spans = spanned.getSpans(0, text.length(), ParcelableSpan.class);
  if (spans.length == 0) {
    return null;
  }

  StringBuilder stringBuilder = new StringBuilder();
  for (ParcelableSpan span : spans) {
    stringBuilder.append("{");
    // Span type.
    stringBuilder.append(span.getClass().getSimpleName());

    // Span text.
    int start = spanned.getSpanStart(span);
    int end = spanned.getSpanEnd(span);
    if (start < 0 || end < 0 || start == end) {
      stringBuilder.append(" invalid index:[");
      stringBuilder.append(start);
      stringBuilder.append(",");
      stringBuilder.append(end);
      stringBuilder.append("]}");
      continue;
    } else {
      stringBuilder.append(" '");
      stringBuilder.append(spanned, start, end);
      stringBuilder.append("'");
    }

    // Extra data.
    if (span instanceof LocaleSpan) {
      LocaleSpan localeSpan = (LocaleSpan) span;
      if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
        Locale locale = localeSpan.getLocale();
        if (locale != null) {
          stringBuilder.append(" locale=");
          stringBuilder.append(locale);
        }
      } else {
        LocaleList localeList = localeSpan.getLocales();
        int size = localeList.size();
        if (size > 0) {
          stringBuilder.append(" locale=[");
          for (int i = 0; i < size - 1; i++) {
            stringBuilder.append(localeList.get(i));
            stringBuilder.append(",");
          }
          stringBuilder.append(localeList.get(size - 1));
          stringBuilder.append("]");
        }
      }

    } else if (span instanceof TtsSpan) {
      TtsSpan ttsSpan = (TtsSpan) span;
      stringBuilder.append(" ttsType=");
      stringBuilder.append(ttsSpan.getType());
      PersistableBundle bundle = ttsSpan.getArgs();
      Set<String> keys = bundle.keySet();
      if (!keys.isEmpty()) {
        for (String key : keys) {
          stringBuilder.append(" ");
          stringBuilder.append(key);
          stringBuilder.append("=");
          stringBuilder.append(bundle.get(key));
        }
      }
    } else if (span instanceof URLSpan) {
      URLSpan urlSpan = (URLSpan) span;
      stringBuilder.append(" url=");
      stringBuilder.append(urlSpan.getURL());
    }
    stringBuilder.append("}");
  }
  return stringBuilder.toString();
}