List of usage examples for android.text SpannableStringBuilder setSpan
public void setSpan(Object what, int start, int end, int flags)
From source file:org.telegram.ui.IdenticonActivity.java
@Override public View createView(Context context) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setAllowOverlayTitle(true); actionBar.setTitle(LocaleController.getString("EncryptionKey", R.string.EncryptionKey)); actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { @Override// ww w .ja v a 2 s . co m public void onItemClick(int id) { if (id == -1) { finishFragment(); } } }); fragmentView = new LinearLayout(context); LinearLayout linearLayout = (LinearLayout) fragmentView; linearLayout.setOrientation(LinearLayout.VERTICAL); linearLayout.setWeightSum(100); linearLayout.setBackgroundColor(ContextCompat.getColor(context, R.color.card_background)); fragmentView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return true; } }); FrameLayout frameLayout = new FrameLayout(context); frameLayout.setPadding(AndroidUtilities.dp(20), AndroidUtilities.dp(20), AndroidUtilities.dp(20), AndroidUtilities.dp(20)); linearLayout.addView(frameLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 50.0f)); ImageView identiconView = new ImageView(context); identiconView.setScaleType(ImageView.ScaleType.FIT_XY); frameLayout.addView(identiconView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); frameLayout = new FrameLayout(context); frameLayout.setBackgroundColor(ContextCompat.getColor(context, R.color.background)); frameLayout.setPadding(AndroidUtilities.dp(10), 0, AndroidUtilities.dp(10), AndroidUtilities.dp(10)); linearLayout.addView(frameLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 50.0f)); TextView textView = new TextView(context); textView.setTextColor(ContextCompat.getColor(context, R.color.secondary_text)); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); textView.setLinksClickable(true); textView.setClickable(true); textView.setMovementMethod(new LinkMovementMethodMy()); //textView.setAutoLinkMask(Linkify.WEB_URLS); textView.setLinkTextColor(Theme.MSG_LINK_TEXT_COLOR); textView.setGravity(Gravity.CENTER); frameLayout.addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); TLRPC.EncryptedChat encryptedChat = MessagesController.getInstance().getEncryptedChat(chat_id); if (encryptedChat != null) { IdenticonDrawable drawable = new IdenticonDrawable(); identiconView.setImageDrawable(drawable); drawable.setEncryptedChat(encryptedChat); TLRPC.User user = MessagesController.getInstance().getUser(encryptedChat.user_id); SpannableStringBuilder hash = new SpannableStringBuilder(); if (encryptedChat.key_hash.length > 16) { String hex = Utilities.bytesToHex(encryptedChat.key_hash); for (int a = 0; a < 32; a++) { if (a != 0) { if (a % 8 == 0) { hash.append('\n'); } else if (a % 4 == 0) { hash.append(' '); } } hash.append(hex.substring(a * 2, a * 2 + 2)); hash.append(' '); } hash.append("\n\n"); } hash.append(AndroidUtilities.replaceTags(LocaleController.formatString("EncryptionKeyDescription", R.string.EncryptionKeyDescription, user.first_name, user.first_name))); final String url = "telegram.org"; int index = hash.toString().indexOf(url); if (index != -1) { hash.setSpan( new URLSpanReplacement( LocaleController.getString("EncryptionKeyLink", R.string.EncryptionKeyLink)), index, index + url.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } textView.setText(hash); } return fragmentView; }
From source file:com.csipsimple.ui.messages.ConversationsAdapter.java
private CharSequence formatMessage(Cursor cursor) { SpannableStringBuilder buf = new SpannableStringBuilder(); /*/* www . j ava 2s.co m*/ String remoteContact = cursor.getString(cursor.getColumnIndex(SipMessage.FIELD_FROM)); if (remoteContact.equals("SELF")) { remoteContact = cursor.getString(cursor.getColumnIndex(SipMessage.FIELD_TO)); buf.append("To: "); } */ String remoteContactFull = cursor.getString(cursor.getColumnIndex(SipMessage.FIELD_FROM_FULL)); CallerInfo callerInfo = CallerInfo.getCallerInfoFromSipUri(mContext, remoteContactFull); if (callerInfo != null && callerInfo.contactExists) { buf.append(callerInfo.name); buf.append(" / "); buf.append(SipUri.getDisplayedSimpleContact(remoteContactFull)); } else { buf.append(SipUri.getDisplayedSimpleContact(remoteContactFull)); } int counter = cursor.getInt(cursor.getColumnIndex("counter")); if (counter > 1) { buf.append(" (" + counter + ") "); } int read = cursor.getInt(cursor.getColumnIndex(SipMessage.FIELD_READ)); // Unread messages are shown in bold if (read == 0) { buf.setSpan(STYLE_BOLD, 0, buf.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE); } return buf; }
From source file:com.fa.mastodon.activity.ComposeActivity.java
private void onUploadSuccess(final QueuedMedia item, Media media) { item.id = media.id;// w ww. ja va 2s . c o m /* Add the upload URL to the text field. Also, keep a reference to the span so if the user * chooses to remove the media, the URL is also automatically removed. */ item.uploadUrl = new URLSpan(media.textUrl); int end = 1 + media.textUrl.length(); SpannableStringBuilder builder = new SpannableStringBuilder(); builder.append(' '); builder.append(media.textUrl); builder.setSpan(item.uploadUrl, 0, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); textEditor.append(builder); waitForMediaLatch.countDown(); }
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 }// w w w .j a v a 2 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; }
From source file:com.ruesga.rview.widget.TagEditTextView.java
public void setTags(Tag[] tags) { // Delete any existent data try {/*from www.ja va 2 s. c o m*/ mTagEdit.getEditableText().clearSpans(); } catch (Exception ex) { // Ignore } int count = mTagList.size() - 1; for (int i = count; i >= 0; i--) { onTagRemoveClick(mTagList.get(i)); } mTagEdit.setText(""); if (tags == null) { return; } // Filter invalid tags for (Tag tag : tags) { Matcher hashTagMatcher = HASH_TAG_PATTERN.matcher(tag.mTag); Matcher userTagMatcher = USER_TAG_PATTERN.matcher(tag.mTag); if (hashTagMatcher.matches() || (mSupportsUserTags && userTagMatcher.matches())) { mTagList.add(tag); } } // Build the spans SpannableStringBuilder builder; if (tags.length > 0) { final String text = String.format("%" + tags.length + "s", CHIP_SEPARATOR_CHAR) .replaceAll(CHIP_SEPARATOR_CHAR, CHIP_REPLACEMENT_CHAR); builder = new SpannableStringBuilder(text); } else { builder = new SpannableStringBuilder(""); } int pos = 0; for (final Tag tag : mTagList) { Bitmap b = createTagChip(tag); tag.w = b.getWidth(); tag.h = b.getHeight(); ImageSpan span = new ImageSpan(getContext(), b, ImageSpan.ALIGN_BOTTOM); builder.setSpan(span, pos, pos + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); pos++; notifyTagCreated(tag); } mTagEdit.setText(builder); mTagEdit.setSelection(mTagEdit.getText().length()); }
From source file:eu.faircode.netguard.ActivitySettings.java
private void markPro(Preference pref, String sku) { if (sku == null || !IAB.isPurchased(sku, this)) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); boolean dark = prefs.getBoolean("dark_theme", false); SpannableStringBuilder ssb = new SpannableStringBuilder(" " + pref.getTitle()); ssb.setSpan( new ImageSpan(this, dark ? R.drawable.ic_shopping_cart_white_24dp : R.drawable.ic_shopping_cart_black_24dp), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); pref.setTitle(ssb);//ww w . ja v a 2 s . c om } }
From source file:com.edible.ocr.CaptureActivity.java
/** * Given either a Spannable String or a regular String and a token, apply * the given CharacterStyle to the span between the tokens. * // w ww.java 2 s .c o m * NOTE: This method was adapted from: * http://www.androidengineer.com/2010/08/easy-method-for-formatting-android.html * * <p> * For example, {@code setSpanBetweenTokens("Hello ##world##!", "##", new * ForegroundColorSpan(0xFFFF0000));} will return a CharSequence {@code * "Hello world!"} with {@code world} in red. * */ private CharSequence setSpanBetweenTokens(CharSequence text, String token, CharacterStyle... cs) { // Start and end refer to the points where the span will apply int tokenLen = token.length(); int start = text.toString().indexOf(token) + tokenLen; int end = text.toString().indexOf(token, start); if (start > -1 && end > -1) { // Copy the spannable string to a mutable spannable string SpannableStringBuilder ssb = new SpannableStringBuilder(text); for (CharacterStyle c : cs) ssb.setSpan(c, start, end, 0); text = ssb; } return text; }
From source file:com.hippo.ehviewer.ui.scene.FavoritesScene.java
private void updateSearchBar() { Context context = getContext2(); if (null == context || null == mUrlBuilder || null == mSearchBar || null == mFavCatArray) { return;/* ww w .j a v a2s .c o m*/ } // Update title int favCat = mUrlBuilder.getFavCat(); String favCatName; if (favCat >= 0 && favCat < 10) { favCatName = mFavCatArray[favCat]; } else if (favCat == FavListUrlBuilder.FAV_CAT_LOCAL) { favCatName = getString(R.string.local_favorites); } else { favCatName = getString(R.string.cloud_favorites); } String keyword = mUrlBuilder.getKeyword(); if (TextUtils.isEmpty(keyword)) { if (!ObjectUtils.equal(favCatName, mOldFavCat)) { mSearchBar.setTitle(getString(R.string.favorites_title, favCatName)); } } else { if (!ObjectUtils.equal(favCatName, mOldFavCat) || !ObjectUtils.equal(keyword, mOldKeyword)) { mSearchBar.setTitle(getString(R.string.favorites_title_2, favCatName, keyword)); } } // Update hint if (!ObjectUtils.equal(favCatName, mOldFavCat)) { Drawable searchImage = DrawableManager.getDrawable(context, R.drawable.v_magnify_x24); SpannableStringBuilder ssb = new SpannableStringBuilder(" "); ssb.append(getString(R.string.favorites_search_bar_hint, favCatName)); int textSize = (int) (mSearchBar.getEditTextTextSize() * 1.25); if (searchImage != null) { searchImage.setBounds(0, 0, textSize, textSize); ssb.setSpan(new ImageSpan(searchImage), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } mSearchBar.setEditTextHint(ssb); } mOldFavCat = favCatName; mOldKeyword = keyword; // Save recent fav cat Settings.putRecentFavCat(mUrlBuilder.getFavCat()); }
From source file:android_network.hetnet.vpn_service.ActivitySettings.java
private void markPro(Preference pref, String sku) { if (sku == null) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); boolean dark = prefs.getBoolean("dark_theme", false); SpannableStringBuilder ssb = new SpannableStringBuilder(" " + pref.getTitle()); ssb.setSpan( new ImageSpan(this, dark ? R.drawable.ic_shopping_cart_white_24dp : R.drawable.ic_shopping_cart_black_24dp), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); pref.setTitle(ssb);//from www . ja v a2 s .com } }
From source file:com.vuze.android.remote.activity.LoginActivity.java
private void setupGuideText(TextView tvLoginGuide) { AndroidUtilsUI.linkify(tvLoginGuide); CharSequence text = tvLoginGuide.getText(); SpannableStringBuilder ss = new SpannableStringBuilder(text); String string = text.toString(); new SpanBubbles().setSpanBubbles(ss, string, "|", tvLoginGuide.getPaint(), AndroidUtilsUI.getStyleColor(this, R.attr.login_text_color), AndroidUtilsUI.getStyleColor(this, R.attr.login_textbubble_color), AndroidUtilsUI.getStyleColor(this, R.attr.login_text_color)); int indexOf = string.indexOf("@@"); if (indexOf >= 0) { int style = ImageSpan.ALIGN_BASELINE; int newHeight = tvLoginGuide.getBaseline(); if (newHeight <= 0) { newHeight = tvLoginGuide.getLineHeight(); style = ImageSpan.ALIGN_BOTTOM; if (newHeight <= 0) { newHeight = 20;//from w w w . ja va 2 s . c o m } } Drawable drawable = ContextCompat.getDrawable(this, R.drawable.guide_icon); int oldWidth = drawable.getIntrinsicWidth(); int oldHeight = drawable.getIntrinsicHeight(); int newWidth = (oldHeight > 0) ? (oldWidth * newHeight) / oldHeight : newHeight; drawable.setBounds(0, 0, newWidth, newHeight); ImageSpan imageSpan = new ImageSpan(drawable, style); ss.setSpan(imageSpan, indexOf, indexOf + 2, 0); } tvLoginGuide.setText(ss); }