android.text.SpannableStringBuilder#replace ( )源码实例Demo

下面列出了android.text.SpannableStringBuilder#replace ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。

源代码1 项目: TelePlus-Android   文件: ChatActivityEnterView.java
public void replaceWithText(int start, int len, CharSequence text, boolean parseEmoji)
{
    try
    {
        SpannableStringBuilder builder = new SpannableStringBuilder(messageEditText.getText());
        builder.replace(start, start + len, text);
        if (parseEmoji)
        {
            Emoji.replaceEmoji(builder, messageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20), false);
        }
        messageEditText.setText(builder);
        messageEditText.setSelection(start + text.length());
    }
    catch (Exception e)
    {
        FileLog.e(e);
    }
}
 
源代码2 项目: TelePlus-Android   文件: ChatActivityEnterView.java
public void replaceWithText(int start, int len, CharSequence text, boolean parseEmoji)
{
    try
    {
        SpannableStringBuilder builder = new SpannableStringBuilder(messageEditText.getText());
        builder.replace(start, start + len, text);
        if (parseEmoji)
        {
            Emoji.replaceEmoji(builder, messageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20), false);
        }
        messageEditText.setText(builder);
        messageEditText.setSelection(start + text.length());
    }
    catch (Exception e)
    {
        FileLog.e(e);
    }
}
 
public void replaceWithText(int start, int len, CharSequence text, boolean parseEmoji) {
    try {
        SpannableStringBuilder builder = new SpannableStringBuilder(messageEditText.getText());
        builder.replace(start, start + len, text);
        if (parseEmoji) {
            Emoji.replaceEmoji(builder, messageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20), false);
        }
        messageEditText.setText(builder);
        if (start + text.length() <= messageEditText.length()) {
            messageEditText.setSelection(start + text.length());
        } else {
            messageEditText.setSelection(messageEditText.length());
        }
    } catch (Exception e) {
        FileLog.e(e);
    }
}
 
源代码4 项目: TelePlus-Android   文件: PaymentFormActivity.java
private void updateSavePaymentField() {
    if (bottomCell[0] == null || sectionCell[2] == null) {
        return;
    }
    if ((paymentForm.password_missing || paymentForm.can_save_credentials) && (webView == null || webView != null && !webviewLoading)) {
        SpannableStringBuilder text = new SpannableStringBuilder(LocaleController.getString("PaymentCardSavePaymentInformationInfoLine1", R.string.PaymentCardSavePaymentInformationInfoLine1));
        if (paymentForm.password_missing) {
            loadPasswordInfo();
            text.append("\n");
            int len = text.length();
            String str2 = LocaleController.getString("PaymentCardSavePaymentInformationInfoLine2", R.string.PaymentCardSavePaymentInformationInfoLine2);
            int index1 = str2.indexOf('*');
            int index2 = str2.lastIndexOf('*');
            text.append(str2);
            if (index1 != -1 && index2 != -1) {
                index1 += len;
                index2 += len;
                bottomCell[0].getTextView().setMovementMethod(new AndroidUtilities.LinkMovementMethodMy());
                text.replace(index2, index2 + 1, "");
                text.replace(index1, index1 + 1, "");
                text.setSpan(new LinkSpan(), index1, index2 - 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
        }
        checkCell1.setEnabled(true);
        bottomCell[0].setText(text);
        checkCell1.setVisibility(View.VISIBLE);
        bottomCell[0].setVisibility(View.VISIBLE);
        sectionCell[2].setBackgroundDrawable(Theme.getThemedDrawable(sectionCell[2].getContext(), R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow));
    } else {
        checkCell1.setVisibility(View.GONE);
        bottomCell[0].setVisibility(View.GONE);
        sectionCell[2].setBackgroundDrawable(Theme.getThemedDrawable(sectionCell[2].getContext(), R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow));
    }
}
 
源代码5 项目: android-quiz-php   文件: CodeTextView.java
@Override
public void run()
{
    SpannableStringBuilder string = new SpannableStringBuilder(mText);

    for (Matcher m = code.matcher( mText ); m.find();) {
        string.replace(
                m.start(),
                m.end(),
                highlight(new SpannableStringBuilder(m.group().replaceAll("\\[\\/?code\\]", "")))
        );
    }

    setText(string);
}
 
源代码6 项目: TelePlus-Android   文件: PaymentFormActivity.java
private void updateSavePaymentField() {
    if (bottomCell[0] == null || sectionCell[2] == null) {
        return;
    }
    if ((paymentForm.password_missing || paymentForm.can_save_credentials) && (webView == null || webView != null && !webviewLoading)) {
        SpannableStringBuilder text = new SpannableStringBuilder(LocaleController.getString("PaymentCardSavePaymentInformationInfoLine1", R.string.PaymentCardSavePaymentInformationInfoLine1));
        if (paymentForm.password_missing) {
            loadPasswordInfo();
            text.append("\n");
            int len = text.length();
            String str2 = LocaleController.getString("PaymentCardSavePaymentInformationInfoLine2", R.string.PaymentCardSavePaymentInformationInfoLine2);
            int index1 = str2.indexOf('*');
            int index2 = str2.lastIndexOf('*');
            text.append(str2);
            if (index1 != -1 && index2 != -1) {
                index1 += len;
                index2 += len;
                bottomCell[0].getTextView().setMovementMethod(new AndroidUtilities.LinkMovementMethodMy());
                text.replace(index2, index2 + 1, "");
                text.replace(index1, index1 + 1, "");
                text.setSpan(new LinkSpan(), index1, index2 - 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
        }
        checkCell1.setEnabled(true);
        bottomCell[0].setText(text);
        checkCell1.setVisibility(View.VISIBLE);
        bottomCell[0].setVisibility(View.VISIBLE);
        sectionCell[2].setBackgroundDrawable(Theme.getThemedDrawable(sectionCell[2].getContext(), R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow));
    } else {
        checkCell1.setVisibility(View.GONE);
        bottomCell[0].setVisibility(View.GONE);
        sectionCell[2].setBackgroundDrawable(Theme.getThemedDrawable(sectionCell[2].getContext(), R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow));
    }
}
 
源代码7 项目: xifan   文件: PatternUtils.java
private static SpannableStringBuilder getUrlTextSpannableString(Context context, String source,
        int size) {
    SpannableStringBuilder builder = new SpannableStringBuilder(source);
    String prefix = " ";
    builder.replace(0, prefix.length(), prefix);
    Drawable drawable = context.getResources().getDrawable(R.mipmap.ic_status_link);
    drawable.setBounds(0, 0, size, size);
    builder.setSpan(new VerticalImageSpan(drawable), prefix.length(), source.length(),
            Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    builder.append(App.getInstance().getString(R.string.text_url_link));
    return builder;
}
 
源代码8 项目: editor   文件: Editor.java
@SuppressWarnings("deprecation")
private void aboutClicked()
{
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setTitle(R.string.appName);

    DateFormat dateFormat = DateFormat.getDateTimeInstance();
    SpannableStringBuilder spannable =
        new SpannableStringBuilder(getText(R.string.version));
    Pattern pattern = Pattern.compile("%s");
    Matcher matcher = pattern.matcher(spannable);
    if (matcher.find())
        spannable.replace(matcher.start(), matcher.end(),
                          BuildConfig.VERSION_NAME);
    matcher.reset(spannable);
    if (matcher.find())
        spannable.replace(matcher.start(), matcher.end(),
                          dateFormat.format(BuildConfig.BUILT));
    builder.setMessage(spannable);

    // Add the button
    builder.setPositiveButton(R.string.ok, null);

    // Create the AlertDialog
    Dialog dialog = builder.show();

    // Set movement method
    TextView text = dialog.findViewById(android.R.id.message);
    if (text != null)
    {
        text.setTextAppearance(builder.getContext(),
                               android.R.style.TextAppearance_Small);
        text.setMovementMethod(LinkMovementMethod.getInstance());
    }
}
 
private static String getTextWithPasswords(CharSequence seq) {
    SpannableStringBuilder lstr = new SpannableStringBuilder(seq);
    for (PasswordSpan span : lstr.getSpans(0, lstr.length(), PasswordSpan.class)) {
        lstr.replace(lstr.getSpanStart(span), lstr.getSpanEnd(span), span.mPassword);
        lstr.removeSpan(span);
    }
    return lstr.toString();
}
 
源代码10 项目: Telegram   文件: TermsOfServiceView.java
private static void addBulletsToText(SpannableStringBuilder builder, char bulletChar, int gapWidth, int color, int radius) {
    for (int i = 0, until = builder.length() - 2; i < until; i++) {
        if (builder.charAt(i) == '\n' && builder.charAt(i + 1) == bulletChar && builder.charAt(i + 2) == ' ') {
            final BulletSpan span = new BulletSpan(gapWidth, color, radius);
            builder.replace(i + 1, i + 3, "\0\0");
            builder.setSpan(span, i + 1, i + 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
    }
}
 
源代码11 项目: AndFChat   文件: BBCodeReader.java
public void doReplacement(SpannableStringBuilder text) {
    if (key != null) {
        String textAsString = text.toString();

        int start = textAsString.indexOf(key);
        text.replace(start, start + key.length(), replacement);
    }
}
 
源代码12 项目: GSYRickText   文件: RichEditText.java
/**
 * 处理话题和表情
 *
 * @param context   上下文
 * @param text      输入文本
 * @param color     颜色
 * @param listTopic 话题列表
 * @return Spannable
 */
private static Spannable resolveTopicInsert(Context context, String text, String color, List<TopicModel> listTopic) {
    Spannable spannable;
    if (listTopic != null && listTopic.size() > 0) {
        Map<String, String> topics = new HashMap<>();
        for (TopicModel topicModel : listTopic) {
            topics.put(topicModel.getTopicName(), topicModel.getTopicName());
        }
        //查找##
        int length = text.length();
        Pattern pattern = Pattern.compile("#[^\\s]+?#");
        Matcher matcher = pattern.matcher(text);
        SpannableStringBuilder spannableStringBuilder =
                new SpannableStringBuilder(text);
        for (int i = 0; i < length; i++) {
            if (matcher.find()) {
                String name = text.substring(matcher.start(), matcher.end());
                if (topics.containsKey(name)) {
                    //直接用span会导致后面没文字的时候新输入的一起变色
                    Spanned htmlText = Html.fromHtml(String.format("<font color='%s'>" + name + "</font>", color));
                    spannableStringBuilder.replace(matcher.start(), matcher.start() + name.length(), htmlText);
                }
            }
        }

        spannable = spannableStringBuilder;
        SmileUtils.addSmiles(context, spannable);
    } else {
        spannable = TextCommonUtils.getEmojiText(context, text);

    }
    SmileUtils.addSmiles(context, spannable);
    return spannable;
}
 
private static CharSequence render(SpannableStringBuilder spannableStringBuilder, ArrayList<IconicFontEngine> engines) {
    int caret = 0;
    List<Pair<Integer, IconicFontEngine>> positions = new ArrayList<>();
    while (true) {
        StringBuilder text = new StringBuilder(spannableStringBuilder.toString());
        int startBracketIndex = text.indexOf("{", caret);
        int endBracketIndex = text.indexOf("}", startBracketIndex + 1);
        if (startBracketIndex == -1 || endBracketIndex == -1) { break; }

        String iconString = text.substring(startBracketIndex + 1, endBracketIndex);
        boolean found = false;
        for (IconicFontEngine engine : engines) {
            Character fontChar = engine.getIconicFontMap().get(iconString);
            if (fontChar != null) {
                spannableStringBuilder.replace(startBracketIndex, endBracketIndex + 1, String.valueOf(fontChar));
                positions.add(new Pair<>(startBracketIndex, engine));
                caret = startBracketIndex + 1;
                found = true;
                break;
            }
        }
        if (!found) {
            Log.w(TAG, "{" + iconString + "} not fount in fontMaps");
            caret = endBracketIndex + 1;
        }
    }

    for (Pair<Integer, IconicFontEngine> pair : positions) {
        setSpan(pair.second.getTypeface(), spannableStringBuilder, pair.first);
    }
    return spannableStringBuilder;
}
 
源代码14 项目: phrase   文件: Phrase.java
@Override void expand(SpannableStringBuilder target, Map<String, CharSequence> data) {
  value = data.get(key);

  int replaceFrom = getFormattedStart();
  // Add 2 to account for the opening and closing brackets.
  int replaceTo = replaceFrom + key.length() + 2;
  target.replace(replaceFrom, replaceTo, value);
}
 
源代码15 项目: grblcontroller   文件: ParsingUtil.java
private static void recursivePrepareSpannableIndexes(
        Context context,
        String fullText,
        SpannableStringBuilder text,
        List<IconFontDescriptorWrapper> iconFontDescriptors,
        int start) {

    // Try to find a {...} in the string and extract expression from it
    String stringText = text.toString();
    int startIndex = stringText.indexOf("{", start);
    if (startIndex == -1) return;
    int endIndex = stringText.indexOf("}", startIndex) + 1;
    if (endIndex == -1) return;
    String expression = stringText.substring(startIndex + 1, endIndex - 1);

    // Split the expression and retrieve the icon key
    String[] strokes = expression.split(" ");
    String key = strokes[0];

    // Loop through the descriptors to find a key match
    IconFontDescriptorWrapper iconFontDescriptor = null;
    Icon icon = null;
    for (int i = 0; i < iconFontDescriptors.size(); i++) {
        iconFontDescriptor = iconFontDescriptors.get(i);
        icon = iconFontDescriptor.getIcon(key);
        if (icon != null) break;
    }

    // If no match, ignore and continue
    if (icon == null) {
        recursivePrepareSpannableIndexes(context, fullText, text, iconFontDescriptors, endIndex);
        return;
    }

    // See if any more stroke within {} should be applied
    float iconSizePx = -1;
    int iconColor = Integer.MAX_VALUE;
    float iconSizeRatio = -1;
    boolean spin = false;
    boolean baselineAligned = false;
    for (int i = 1; i < strokes.length; i++) {
        String stroke = strokes[i];

        // Look for "spin"
        if (stroke.equalsIgnoreCase("spin")) {
            spin = true;
        }

        // Look for "baseline"
        else if (stroke.equalsIgnoreCase("baseline")) {
            baselineAligned = true;
        }

        // Look for an icon size
        else if (stroke.matches("([0-9]*(\\.[0-9]*)?)dp")) {
            iconSizePx = dpToPx(context, Float.valueOf(stroke.substring(0, stroke.length() - 2)));
        } else if (stroke.matches("([0-9]*(\\.[0-9]*)?)sp")) {
            iconSizePx = spToPx(context, Float.valueOf(stroke.substring(0, stroke.length() - 2)));
        } else if (stroke.matches("([0-9]*)px")) {
            iconSizePx = Integer.valueOf(stroke.substring(0, stroke.length() - 2));
        } else if (stroke.matches("@dimen/(.*)")) {
            iconSizePx = getPxFromDimen(context, context.getPackageName(), stroke.substring(7));
            if (iconSizePx < 0)
                throw new IllegalArgumentException("Unknown resource " + stroke + " in \"" + fullText + "\"");
        } else if (stroke.matches("@android:dimen/(.*)")) {
            iconSizePx = getPxFromDimen(context, ANDROID_PACKAGE_NAME, stroke.substring(15));
            if (iconSizePx < 0)
                throw new IllegalArgumentException("Unknown resource " + stroke + " in \"" + fullText + "\"");
        } else if (stroke.matches("([0-9]*(\\.[0-9]*)?)%")) {
            iconSizeRatio = Float.valueOf(stroke.substring(0, stroke.length() - 1)) / 100f;
        }

        // Look for an icon color
        else if (stroke.matches("#([0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})")) {
            iconColor = Color.parseColor(stroke);
        } else if (stroke.matches("@color/(.*)")) {
            iconColor = getColorFromResource(context, context.getPackageName(), stroke.substring(7));
            if (iconColor == Integer.MAX_VALUE)
                throw new IllegalArgumentException("Unknown resource " + stroke + " in \"" + fullText + "\"");
        } else if (stroke.matches("@android:color/(.*)")) {
            iconColor = getColorFromResource(context, ANDROID_PACKAGE_NAME, stroke.substring(15));
            if (iconColor == Integer.MAX_VALUE)
                throw new IllegalArgumentException("Unknown resource " + stroke + " in \"" + fullText + "\"");
        } else {
            throw new IllegalArgumentException("Unknown expression " + stroke + " in \"" + fullText + "\"");
        }
    }

    // Replace the character and apply the typeface
    text = text.replace(startIndex, endIndex, "" + icon.character());
    text.setSpan(new CustomTypefaceSpan(icon,
                    iconFontDescriptor.getTypeface(context),
                    iconSizePx, iconSizeRatio, iconColor, spin, baselineAligned),
            startIndex, startIndex + 1,
            Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
    recursivePrepareSpannableIndexes(context, fullText, text, iconFontDescriptors, startIndex);
}
 
源代码16 项目: OpenHub   文件: IssueTimelineAdapter.java
void setDesc(IssueEvent model){
            SpannableStringBuilder text = new SpannableStringBuilder(model.getActor().getLogin());
            text.append(" ");
            String info;
            switch (model.getType()){
                case reopened:
                    text.append(getString(R.string.issue_reopened));
                    break;
                case closed:
                    text.append(getString(R.string.issue_close));
                    break;
                case renamed:
                    text.append(getString(R.string.issue_modified));
                    break;
                case locked:
                    text.append(getString(R.string.issue_locked_conversation));
                    break;
                case unlocked:
                    text.append(getString(R.string.issue_unlocked_conversation));
                    break;
                case crossReferenced:
                    if(model.getSource().getType() != null){
                        info = String.format(getString(R.string.issue_referenced),
                                "#" + model.getSource().getIssue().getTitle());
                        text.append(info);
                    }
                    break;
                case assigned:
                    info = String.format(getString(R.string.issue_assigned), model.getAssignee().getLogin());
                    text.append(info);
                    break;
                case unassigned:
                    text.append(getString(R.string.issue_unassigned));
                    break;
                case milestoned:
                    info = String.format(getString(R.string.issue_added_to_milestone),
                            model.getMilestone().getTitle());
                    text.append(info);
                    break;
                case demilestoned:
                    info = String.format(getString(R.string.issue_removed_from_milestone),
                            model.getMilestone().getTitle());
                    text.append(info);
                    break;
                case commentDeleted:
                    text.append(getString(R.string.issue_delete_comment));
                    break;
                case labeled:
                    info = String.format(getString(R.string.issue_add_label), "[label]");
                    text.append(info);
                    break;
                case unlabeled:
                    info = String.format(getString(R.string.issue_remove_label), "[label]");
                    text.append(info);
                    break;
                default:
//                    eventIcon.setBackgroundColor(context.getResources().getColor(R.color.transparent));
                    break;
            }

            int labelPos = text.toString().indexOf("[label]");
            Label label = model.getLabel();
            if(label != null && labelPos >= 0){
                text.replace(labelPos, labelPos + 7, label.getName());
                text.setSpan(new IssueLabelSpan(context, label),
                        labelPos, labelPos + label.getName().length(), 0);
            }

            String timeStr = StringUtils.getNewsTimeStr(context, model.getCreatedAt());
            text.append(" ").append(timeStr);
            desc.setText(text);
        }
 
源代码17 项目: TokenAutoComplete   文件: SpanUtils.java
@Nullable
public static Spanned ellipsizeWithSpans(@Nullable CharSequence prefix, @Nullable CountSpan countSpan,
                                       int tokenCount, @NonNull TextPaint paint,
                                       @NonNull CharSequence originalText, float maxWidth) {

    float countWidth = 0;
    if (countSpan != null) {
        //Assume the largest possible number of items for measurement
        countSpan.setCount(tokenCount);
        countWidth = countSpan.getCountTextWidthForPaint(paint);
    }

    EllipsizeCallback ellipsizeCallback = new EllipsizeCallback();
    CharSequence tempEllipsized = TextUtils.ellipsize(originalText, paint, maxWidth - countWidth,
            TextUtils.TruncateAt.END, false, ellipsizeCallback);
    SpannableStringBuilder ellipsized = new SpannableStringBuilder(tempEllipsized);
    if (tempEllipsized instanceof Spanned) {
        TextUtils.copySpansFrom((Spanned)tempEllipsized, 0, tempEllipsized.length(), Object.class, ellipsized, 0);
    }

    if (prefix != null && prefix.length() > ellipsizeCallback.start) {
        //We ellipsized part of the prefix, so put it back
        ellipsized.replace(0, ellipsizeCallback.start, prefix);
        ellipsizeCallback.end = ellipsizeCallback.end + prefix.length() - ellipsizeCallback.start;
        ellipsizeCallback.start = prefix.length();
    }

    if (ellipsizeCallback.start != ellipsizeCallback.end) {

        if (countSpan != null) {
            int visibleCount = ellipsized.getSpans(0, ellipsized.length(), TokenCompleteTextView.TokenImageSpan.class).length;
            countSpan.setCount(tokenCount - visibleCount);
            ellipsized.replace(ellipsizeCallback.start, ellipsized.length(), countSpan.getCountText());
            ellipsized.setSpan(countSpan, ellipsizeCallback.start, ellipsized.length(),
                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        return ellipsized;
    }
    //No ellipses necessary
    return null;
}
 
源代码18 项目: currency   文件: AboutPreference.java
@Override
protected void onBindDialogView(View view)
{
    super.onBindDialogView(view);

    // Get version text view
    TextView version = view.findViewById(R.id.about);

    // Set version in text view
    if (version != null)
    {
        SpannableStringBuilder builder =
            new SpannableStringBuilder(version.getText());
        Pattern pattern = Pattern.compile("%s");
        Matcher matcher = pattern.matcher(builder);
        if (matcher.find())
            builder.replace(matcher.start(), matcher.end(),
                            BuildConfig.VERSION_NAME);
        version.setText(builder);
        version.setMovementMethod(LinkMovementMethod.getInstance());
    }

    // Get built text view
    TextView built = view.findViewById(R.id.built);

    // Set built date in text view
    if (built != null)
    {
        String d = built.getText().toString();
        DateFormat dateFormat = DateFormat.getDateTimeInstance();
        String s =
            String.format(d, dateFormat.format(BuildConfig.BUILT));
        built.setText(s);
    }

    // Get copyright text view
    TextView copyright = view.findViewById(R.id.copyright);

    // Set movement method
    if (copyright != null)
        copyright.setMovementMethod(LinkMovementMethod.getInstance());

    // Get licence text view
    TextView licence = view.findViewById(R.id.licence);

    // Set movement method
    if (licence != null)
        licence.setMovementMethod(LinkMovementMethod.getInstance());
}
 
源代码19 项目: GSYRickText   文件: RichEditText.java
/**
 * 处理at某人
 *
 * @param text      输入文本
 * @param spannable 处理过的文本
 * @param color     颜色
 * @param listUser  用户列表
 * @return Spannable
 */
private Spannable resolveAtInsert(String text, Spannable spannable, String color, List<UserModel> listUser) {

    if (listUser == null || listUser.size() <= 0) {
        return spannable;
    }

    //此处保存名字的键值
    Map<String, String> names = new HashMap<>();
    if (listUser.size() > 0) {
        for (UserModel userModel : listUser) {
            names.put(userModel.getUser_name(), userModel.getUser_name());
        }
    }
    int length = spannable.length();
    Pattern pattern = Pattern.compile("@[^\\s]+\\s?");
    Matcher matcher = pattern.matcher(spannable);
    SpannableStringBuilder spannableStringBuilder =
            new SpannableStringBuilder(spannable);
    for (int i = 0; i < length; i++) {
        if (matcher.find()) {
            String name = text.substring(matcher.start(), matcher.end());
            if (names.containsKey(name.replace("\b", "").replace(" ", ""))) {
                //直接用span会导致后面没文字的时候新输入的一起变色
                Spanned htmlText = Html.fromHtml(String.format("<font color='%s'>" + name + "</font>", color));
                spannableStringBuilder.replace(matcher.start(), matcher.start() + name.length(), htmlText);
                int index = matcher.start() + htmlText.length();
                if (index < text.length()) {
                    if (" ".equals(text.subSequence(index - 1, index))) {
                        spannableStringBuilder.replace(index - 1, index, "\b");
                    }
                } else {
                    if (text.substring(index - 1).equals(" ")) {
                        spannableStringBuilder.replace(index - 1, index, "\b");
                    } else {
                        //如果是最后面的没有空格,补上\b
                        spannableStringBuilder.insert(index, "\b");
                    }
                }
            }
        }
    }
    return spannableStringBuilder;
}
 
源代码20 项目: twitter-kit-android   文件: TweetTextLinkifier.java
/**
 * Swaps display urls in for t.co urls and adjusts the remaining entity indices.
 *
 * @param spannable          The final formatted text that we are building
 * @param entities           The combined list of media and url entities
 * @param strippedEntity     The trailing entity that we should strip from the text
 * @param linkListener       The link click listener to attach to the span
 * @param linkColor          The link color
 * @param linkHighlightColor The link background color when pressed
 */
private static void addUrlEntities(final SpannableStringBuilder spannable,
        final List<FormattedUrlEntity> entities,
        final FormattedUrlEntity strippedEntity,
        final LinkClickListener linkListener,
        final int linkColor, final int linkHighlightColor) {
    if (entities == null || entities.isEmpty()) return;

    int offset = 0;
    int len;
    int start;
    int end;
    for (final FormattedUrlEntity url : entities) {
        start = url.start - offset;
        end = url.end - offset;
        if (start >= 0 && end <= spannable.length()) {
            // replace the last photo url with empty string, we can use the start indices as
            // as simple check, since none of this will work anyways if we have overlapping
            // entities
            if (strippedEntity != null && strippedEntity.start == url.start) {
                spannable.replace(start, end, "");
                len = end - start;
                offset += len;
            } else if (!TextUtils.isEmpty(url.displayUrl)) {
                spannable.replace(start, end, url.displayUrl);
                len = end - (start + url.displayUrl.length());
                end -= len;
                offset += len;

                final CharacterStyle span = new ClickableLinkSpan(linkHighlightColor,
                        linkColor, false) {
                    @Override
                    public void onClick(View widget) {
                        if (linkListener == null) return;
                        linkListener.onUrlClicked(url.url);
                    }
                };
                spannable.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
        }
    }
}