Example usage for android.text SpannableStringBuilder subSequence

List of usage examples for android.text SpannableStringBuilder subSequence

Introduction

In this page you can find the example usage for android.text SpannableStringBuilder subSequence.

Prototype

public CharSequence subSequence(int start, int end) 

Source Link

Document

Return a new CharSequence containing a copy of the specified range of this buffer, including the overlapping spans.

Usage

From source file:com.keylesspalace.tusky.util.LinkHelper.java

/**
 * Finds links, mentions, and hashtags in a piece of text and makes them clickable, associating
 * them with callbacks to notify when they're clicked.
 *
 * @param view the returned text will be put in
 * @param content containing text with mentions, links, or hashtags
 * @param mentions any '@' mentions which are known to be in the content
 * @param listener to notify about particular spans that are clicked
 *//*  w  w  w .  j  a  v  a2  s .  com*/
public static void setClickableText(TextView view, Spanned content, @Nullable Status.Mention[] mentions,
        final LinkListener listener) {

    SpannableStringBuilder builder = new SpannableStringBuilder(content);
    URLSpan[] urlSpans = content.getSpans(0, content.length(), URLSpan.class);
    for (URLSpan span : urlSpans) {
        int start = builder.getSpanStart(span);
        int end = builder.getSpanEnd(span);
        int flags = builder.getSpanFlags(span);
        CharSequence text = builder.subSequence(start, end);
        if (text.charAt(0) == '#') {
            final String tag = text.subSequence(1, text.length()).toString();
            ClickableSpan newSpan = new ClickableSpan() {
                @Override
                public void onClick(View widget) {
                    listener.onViewTag(tag);
                }

                @Override
                public void updateDrawState(TextPaint ds) {
                    super.updateDrawState(ds);
                    ds.setUnderlineText(false);
                }
            };
            builder.removeSpan(span);
            builder.setSpan(newSpan, start, end, flags);
        } else if (text.charAt(0) == '@' && mentions != null && mentions.length > 0) {
            String accountUsername = text.subSequence(1, text.length()).toString();
            /* There may be multiple matches for users on different instances with the same
             * username. If a match has the same domain we know it's for sure the same, but if
             * that can't be found then just go with whichever one matched last. */
            String id = null;
            for (Status.Mention mention : mentions) {
                if (mention.localUsername.equalsIgnoreCase(accountUsername)) {
                    id = mention.id;
                    if (mention.url.contains(getDomain(span.getURL()))) {
                        break;
                    }
                }
            }
            if (id != null) {
                final String accountId = id;
                ClickableSpan newSpan = new ClickableSpan() {
                    @Override
                    public void onClick(View widget) {
                        listener.onViewAccount(accountId);
                    }

                    @Override
                    public void updateDrawState(TextPaint ds) {
                        super.updateDrawState(ds);
                        ds.setUnderlineText(false);
                    }
                };
                builder.removeSpan(span);
                builder.setSpan(newSpan, start, end, flags);
            }
        } else {
            ClickableSpan newSpan = new CustomURLSpan(span.getURL());
            builder.removeSpan(span);
            builder.setSpan(newSpan, start, end, flags);
        }
    }
    view.setText(builder);
    view.setLinksClickable(true);
    view.setMovementMethod(LinkMovementMethod.getInstance());
}

From source file:com.xinheng.crash.CrashListAdapter.java

@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
    String crash = mData[position];
    holder.log = crash;/*from   w  ww  . jav  a  2s.c  o  m*/
    if (crash != null) {
        setSpaceState(holder, /*show = */ crash.startsWith("at "));

        if (crash.startsWith("Caused by")) {
            holder.title.setTypeface(null, Typeface.BOLD);
            holder.title.setTextColor(0xdeffffff);
        } else {
            holder.title.setTypeface(null, Typeface.NORMAL);
            holder.title.setTextColor(0xffef4545);
        }

        if (mPackageName != null && crash.contains(mPackageName) && crash.indexOf("(") > -1) {
            holder.itemView.setSelected(true);
            int indexOfC = crash.indexOf("(");
            String atPackage = crash.substring(0, indexOfC);
            SpannableStringBuilder builder = new SpannableStringBuilder(atPackage)
                    .append(StringStyleUtils.format(holder.title.getContext(), " " + crash.substring(indexOfC),
                            R.style.LineTextAppearance));
            CharSequence title = builder.subSequence(0, builder.length());
            holder.title.setText(title);

        } else {
            holder.itemView.setSelected(false);
            holder.title.setText(crash);
        }
    }
}

From source file:me.drakeet.library.ui.CrashListAdapter.java

@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
    String crash = mData[position];
    holder.log = crash;/* w w w  .j a v a  2s . com*/
    if (crash != null) {
        setSpaceState(holder, /*show = */ crash.startsWith("at "));

        if (crash.startsWith("Caused by")) {
            holder.title.setTypeface(null, Typeface.BOLD);
            holder.title.setTextColor(0xdeffffff);
        } else {
            holder.title.setTypeface(null, Typeface.NORMAL);
            holder.title.setTextColor(0xffef4545);
        }

        if (mPackageName != null && crash.contains(mPackageName)) {
            holder.itemView.setSelected(true);
            int indexOfC = crash.indexOf("(");
            if (indexOfC >= 0) {
                String atPackage = crash.substring(0, indexOfC);
                SpannableStringBuilder builder = new SpannableStringBuilder(atPackage)
                        .append(StringStyleUtils.format(holder.title.getContext(),
                                " " + crash.substring(indexOfC), R.style.LineTextAppearance));
                CharSequence title = builder.subSequence(0, builder.length());
                holder.title.setText(title);
            } else {
                holder.title.setText(crash);
            }
        } else {
            holder.itemView.setSelected(false);
            holder.title.setText(crash);
        }
    }
}

From source file:com.juick.android.JuickMessagesAdapter.java

private static void setStyleSpans(SpannableStringBuilder ssb, int ssbOffset, Object what, String styleChar) {
    String txt;/*from  ww  w .j a  va2  s  . c  om*/
    txt = ssb.subSequence(ssbOffset, ssb.length()).toString();
    txt = " " + txt + " ";
    ssbOffset -= 1;
    //
    int scan = 0;
    int cnt = 0;
    while (cnt++ < 20) { // don't need bugs in production.
        int ix = txt.indexOf(styleChar, scan);
        if (ix < 0)
            break;
        if (" \n".indexOf(txt.charAt(ix - 1)) != -1) {
            int ix2 = txt.indexOf(styleChar, ix + 1);
            if (ix2 < 0)
                break;
            if (" \n".indexOf(txt.charAt(ix2 + 1)) == -1 // not ends with space
                    || txt.substring(ix, ix2).indexOf("\n") != -1) { // spans several lines
                scan = ix2; // not ok
                continue;
            } else {
                CharacterStyle span = null;
                CharacterStyle span2 = null;
                // found needed stuff
                if (what instanceof Integer && (((Integer) what) == Typeface.BOLD)) {
                    span = new StyleSpan(Typeface.BOLD);
                    if (helvNueFonts) {
                        span2 = new CustomTypefaceSpan("", JuickAdvancedApplication.helvNueBold);
                    }
                }
                if (what instanceof Integer && (((Integer) what) == Typeface.ITALIC)) {
                    span = new StyleSpan(Typeface.ITALIC);
                }
                if (what == UnderlineSpan.class) {
                    span = new UnderlineSpan();
                }
                if (span != null && ix2 - ix > 1) {
                    ssb.delete(ssbOffset + ix, ssbOffset + ix + 1); // delete styling char
                    txt = stringDelete(txt, ix, ix + 1);
                    ix2--; // moves, too
                    ssb.delete(ssbOffset + ix2, ssbOffset + ix2 + 1); // second char deleted
                    txt = stringDelete(txt, ix2, ix2 + 1);
                    ssb.setSpan(span, ssbOffset + ix, ssbOffset + ix2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    if (span2 != null) {
                        ssb.setSpan(span2, ssbOffset + ix, ssbOffset + ix2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    }
                }
                scan = ix2;
            }
        }
    }
}

From source file:com.juick.android.JuickMessagesAdapter.java

public static ParsedMessage formatMessageText(final Context ctx, final JuickMessage jmsg, boolean condensed) {
    if (jmsg.parsedText != null) {
        return (ParsedMessage) jmsg.parsedText; // was parsed before
    }/*from   w ww.  j av  a2  s .c  o m*/
    getColorTheme(ctx);
    SpannableStringBuilder ssb = new SpannableStringBuilder();
    int spanOffset = 0;
    final boolean isMainMessage = jmsg.getRID() == 0;
    final boolean doCompactComment = !isMainMessage && compactComments;
    if (jmsg.continuationInformation != null) {
        ssb.append(jmsg.continuationInformation + "\n");
        ssb.setSpan(new StyleSpan(Typeface.ITALIC), spanOffset, ssb.length() - 1,
                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    }
    //
    // NAME
    //
    spanOffset = ssb.length();
    String name = '@' + jmsg.User.UName;
    int userNameStart = ssb.length();
    ssb.append(name);
    int userNameEnd = ssb.length();
    StyleSpan userNameBoldSpan;
    ForegroundColorSpan userNameColorSpan;
    ssb.setSpan(userNameBoldSpan = new StyleSpan(Typeface.BOLD), spanOffset, ssb.length(),
            Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    ssb.setSpan(
            userNameColorSpan = new ForegroundColorSpan(
                    colorTheme.getColor(ColorsTheme.ColorKey.USERNAME, 0xFFC8934E)),
            spanOffset, ssb.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

    if (helvNueFonts) {
        ssb.setSpan(new CustomTypefaceSpan("", JuickAdvancedApplication.helvNueBold), spanOffset, ssb.length(),
                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    }
    ssb.append(' ');
    spanOffset = ssb.length();

    if (!condensed) {
        //
        // TAGS
        //
        String tags = jmsg.getTags();
        if (feedlyFonts)
            tags = tags.toUpperCase();
        ssb.append(tags + "\n");
        if (tags.length() > 0) {
            ssb.setSpan(new ForegroundColorSpan(colorTheme.getColor(ColorsTheme.ColorKey.TAGS, 0xFF0000CC)),
                    spanOffset, ssb.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            if (feedlyFonts) {
                ssb.setSpan(new CustomTypefaceSpan("", JuickAdvancedApplication.dinWebPro), spanOffset,
                        ssb.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            } else if (helvNueFonts) {
                ssb.setSpan(new CustomTypefaceSpan("", JuickAdvancedApplication.helvNue), spanOffset,
                        ssb.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }

        }
        spanOffset = ssb.length();
    }
    if (jmsg.translated) {
        //
        // 'translated'
        //
        ssb.append("translated: ");
        ssb.setSpan(
                new ForegroundColorSpan(colorTheme.getColor(ColorsTheme.ColorKey.TRANSLATED_LABEL, 0xFF4ec856)),
                spanOffset, ssb.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        ssb.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), spanOffset, ssb.length(),
                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        spanOffset = ssb.length();
    }
    int bodyOffset = ssb.length();
    int messageNumberStart = -1, messageNumberEnd = -1;
    if (showNumbers(ctx) && !condensed) {
        //
        // numbers
        //
        if (isMainMessage) {
            messageNumberStart = ssb.length();
            ssb.append(jmsg.getDisplayMessageNo());
            messageNumberEnd = ssb.length();
        } else {
            ssb.append("/" + jmsg.getRID());
            if (jmsg.getReplyTo() != 0) {
                ssb.append("->" + jmsg.getReplyTo());
            }
        }
        ssb.append(" ");
        ssb.setSpan(new ForegroundColorSpan(colorTheme.getColor(ColorsTheme.ColorKey.MESSAGE_ID, 0xFFa0a5bd)),
                spanOffset, ssb.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        spanOffset = ssb.length();
    }
    //
    // MESSAGE BODY
    //
    String txt = Censor.getCensoredText(jmsg.Text);
    if (!condensed) {
        if (jmsg.Photo != null) {
            txt = jmsg.Photo + "\n" + txt;
        }
        if (jmsg.Video != null) {
            txt = jmsg.Video + "\n" + txt;
        }
    }
    ssb.append(txt);
    boolean ssbChanged = false; // allocation optimization
    // Highlight links http://example.com/
    ArrayList<ExtractURLFromMessage.FoundURL> foundURLs = ExtractURLFromMessage.extractUrls(txt, jmsg.getMID());
    ArrayList<String> urls = new ArrayList<String>();
    for (ExtractURLFromMessage.FoundURL foundURL : foundURLs) {
        setSSBSpan(ssb, new ForegroundColorSpan(colorTheme.getColor(ColorsTheme.ColorKey.URLS, 0xFF0000CC)),
                spanOffset + foundURL.start, spanOffset + foundURL.end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        urls.add(foundURL.url);
        if (foundURL.title != null) {
            ssb.replace(spanOffset + foundURL.title.start - 1, spanOffset + foundURL.title.start, " ");
            ssb.replace(spanOffset + foundURL.title.end, spanOffset + foundURL.title.end + 1, " ");
            ssb.replace(spanOffset + foundURL.start - 1, spanOffset + foundURL.start, "(");
            ssb.replace(spanOffset + foundURL.end, spanOffset + foundURL.end + 1, ")");
            ssb.setSpan(new StyleSpan(Typeface.BOLD), spanOffset + foundURL.title.start,
                    spanOffset + foundURL.title.end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        ssbChanged = true;
    }
    // bold italic underline
    if (jmsg.Text.indexOf("*") != -1) {
        setStyleSpans(ssb, spanOffset, Typeface.BOLD, "*");
        ssbChanged = true;
    }
    if (jmsg.Text.indexOf("/") != 0) {
        setStyleSpans(ssb, spanOffset, Typeface.ITALIC, "/");
        ssbChanged = true;
    }
    if (jmsg.Text.indexOf("_") != 0) {
        setStyleSpans(ssb, spanOffset, UnderlineSpan.class, "_");
        ssbChanged = true;
    }
    if (ssbChanged) {
        txt = ssb.subSequence(spanOffset, ssb.length()).toString(); // ssb was modified in between
    }

    // Highlight nick
    String accountName = XMPPService.getMyAccountName(jmsg.getMID(), ctx);
    if (accountName != null) {
        int scan = spanOffset;
        String nickScanArea = (ssb + " ").toUpperCase();
        while (true) {
            int myNick = nickScanArea.indexOf("@" + accountName.toUpperCase(), scan);
            if (myNick != -1) {
                if (!isNickPart(nickScanArea.charAt(myNick + accountName.length() + 1))) {
                    setSSBSpan(ssb,
                            new BackgroundColorSpan(
                                    colorTheme.getColor(ColorsTheme.ColorKey.USERNAME_ME, 0xFF938e00)),
                            myNick - 1, myNick + accountName.length() + 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                }
                scan = myNick + 1;
            } else {
                break;
            }
        }
    }

    // Highlight messages #1234
    int pos = 0;
    Matcher m = getCrossReferenceMsgPattern(jmsg.getMID()).matcher(txt);
    while (m.find(pos)) {
        ssb.setSpan(new ForegroundColorSpan(colorTheme.getColor(ColorsTheme.ColorKey.URLS, 0xFF0000CC)),
                spanOffset + m.start(), spanOffset + m.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        pos = m.end();
    }

    SpannableStringBuilder compactDt = null;
    if (!condensed) {

        // found messages count (search results)
        if (jmsg.myFoundCount != 0 || jmsg.hisFoundCount != 0) {
            ssb.append("\n");
            int where = ssb.length();
            if (jmsg.myFoundCount != 0) {
                ssb.append(ctx.getString(R.string.MyReplies_) + jmsg.myFoundCount + "  ");
            }
            if (jmsg.hisFoundCount != 0) {
                ssb.append(ctx.getString(R.string.UserReplies_) + jmsg.hisFoundCount);
            }
            ssb.setSpan(
                    new ForegroundColorSpan(
                            colorTheme.getColor(ColorsTheme.ColorKey.TRANSLATED_LABEL, 0xFF4ec856)),
                    where, ssb.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }

        int rightPartOffset = spanOffset = ssb.length();

        if (!doCompactComment) {
            //
            // TIME (bottom of message)
            //

            try {
                DateFormat df = new SimpleDateFormat("HH:mm dd/MMM/yy");
                String date = jmsg.Timestamp != null ? df.format(jmsg.Timestamp) : "[bad date]";
                if (date.endsWith("/76"))
                    date = date.substring(0, date.length() - 3); // special case for no year in datasource
                ssb.append("\n" + date + " ");
            } catch (Exception e) {
                ssb.append("\n[fmt err] ");
            }

            ssb.setSpan(new ForegroundColorSpan(colorTheme.getColor(ColorsTheme.ColorKey.DATE, 0xFFAAAAAA)),
                    spanOffset, ssb.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        } else {
            compactDt = new SpannableStringBuilder();
            try {
                if (true || jmsg.deltaTime != Long.MIN_VALUE) {
                    compactDt.append(com.juickadvanced.Utils.toRelaviteDate(jmsg.Timestamp.getTime(), russian));
                } else {
                    DateFormat df = new SimpleDateFormat("HH:mm dd/MMM/yy");
                    String date = jmsg.Timestamp != null ? df.format(jmsg.Timestamp) : "[bad date]";
                    if (date.endsWith("/76"))
                        date = date.substring(0, date.length() - 3); // special case for no year in datasource
                    compactDt.append(date);
                }
            } catch (Exception e) {
                compactDt.append("\n[fmt err] ");
            }
            compactDt.setSpan(
                    new ForegroundColorSpan(colorTheme.getColor(ColorsTheme.ColorKey.DATE, 0xFFAAAAAA)), 0,
                    compactDt.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

        }

        spanOffset = ssb.length();

        //
        // Number of REPLIES
        //
        if (jmsg.replies > 0) {
            String replies = Replies + jmsg.replies;
            ssb.append(" " + replies);
            ssb.setSpan(
                    new ForegroundColorSpan(
                            colorTheme.getColor(ColorsTheme.ColorKey.NUMBER_OF_COMMENTS, 0xFFC8934E)),
                    spanOffset, ssb.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            ssb.setSpan(new WrapTogetherSpan() {
            }, spanOffset, ssb.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        if (!doCompactComment) {
            // right align
            ssb.setSpan(new AlignmentSpan.Standard(Alignment.ALIGN_OPPOSITE), rightPartOffset, ssb.length(),
                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
    }

    if (helvNueFonts) {
        ssb.setSpan(new CustomTypefaceSpan("", JuickAdvancedApplication.helvNue), bodyOffset, ssb.length(),
                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    }

    LeadingMarginSpan.LeadingMarginSpan2 userpicSpan = null;
    if (showUserpics(ctx) && !condensed) {
        userpicSpan = new LeadingMarginSpan.LeadingMarginSpan2() {
            @Override
            public int getLeadingMarginLineCount() {
                if (_wrapUserpics) {
                    return 2;
                } else {
                    return 22222;
                }
            }

            @Override
            public int getLeadingMargin(boolean first) {
                if (first) {
                    return (int) (2 * getLineHeight(ctx, (double) textScale));
                } else {
                    return 0;
                }
            }

            @Override
            public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, int top, int baseline, int bottom,
                    CharSequence text, int start, int end, boolean first, Layout layout) {
            }
        };
        ssb.setSpan(userpicSpan, 0, ssb.length(), 0);
    }
    ParsedMessage parsedMessage = new ParsedMessage(ssb, urls);
    parsedMessage.userpicSpan = userpicSpan;
    parsedMessage.userNameBoldSpan = userNameBoldSpan;
    parsedMessage.userNameColorSpan = userNameColorSpan;
    parsedMessage.userNameStart = userNameStart;
    parsedMessage.userNameEnd = userNameEnd;
    parsedMessage.messageNumberStart = messageNumberStart;
    parsedMessage.messageNumberEnd = messageNumberEnd;
    parsedMessage.compactDate = compactDt;
    return parsedMessage;
}