Skip to content

Instantly share code, notes, and snippets.

@li2
Last active May 18, 2018 14:21
Show Gist options
  • Save li2/f962c1c6eb13b74796f2 to your computer and use it in GitHub Desktop.
Save li2/f962c1c6eb13b74796f2 to your computer and use it in GitHub Desktop.
SpannableString class to implement text with foreground color, background color, underline, strikethrough, bold & italic style, relative font size, superscript, subscript, URLs, clickable, text composed with image, and so on. #tags: android-view
/**
* Created by weiyi on 3/28/16.
* http://li2.me/2016/03/android-spannablestring-example.html
* https://github.com/li2/Learning_Android_Open_Source/tree/master/AndroidTextSample
*/
public class SpannableStringApiActivity extends AppCompatActivity {
@Bind(R.id.textView) TextView mTextView;
@Bind(R.id.spannableForegroundColor) TextView mForegroundColorTextView;
@Bind(R.id.spannableBackgroundColor) TextView mBackgroundColorTextView;
@Bind(R.id.spannableUnderline) TextView mUnderlineTextView;
@Bind(R.id.spannableStrikethrough) TextView mStrikethroughTextView;
@Bind(R.id.spannableStyle) TextView mStyleTextView;
@Bind(R.id.spannableRelativeSize) TextView mRelativeSizeTextView;
@Bind(R.id.spannableSuperscript) TextView mSuperscriptTextview;
@Bind(R.id.spannableSubscript) TextView mSubscriptTextview;
@Bind(R.id.spannableUrl) TextView mUrlTextView;
@Bind(R.id.spannableImage) TextView mImageTextView;
private static final String CONTENT = "time is 52h 1314m . ";
private static final int START = 8; // the index of 5
private static final int END = 17; // the index of m
private static final String URL = "http://li2.me";
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_spannable_api);
ButterKnife.bind(this);
setTitle(R.string.action_title_spannable_string_api);
// plain text
mTextView.setText(CONTENT + "Plain");
// foreground color text
ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(Color.YELLOW);
setSpanText(CONTENT + "Colored", mForegroundColorTextView, foregroundColorSpan);
// background color text
BackgroundColorSpan backgroundColorSpan = new BackgroundColorSpan(Color.YELLOW);
setSpanText(CONTENT + "Highlighted", mBackgroundColorTextView, backgroundColorSpan);
// under line text
UnderlineSpan underlineSpan = new UnderlineSpan();
setSpanText(CONTENT + "Underlined", mUnderlineTextView, underlineSpan);
// strikethrough text
StrikethroughSpan strikethroughSpan = new StrikethroughSpan();
setSpanText(CONTENT + "Strikethrough", mStrikethroughTextView, strikethroughSpan);
// Style text
StyleSpan styleSpan = new StyleSpan(Typeface.BOLD_ITALIC);
setSpanText(CONTENT + "Bold & Italic", mStyleTextView, styleSpan);
// Relative size text
RelativeSizeSpan relativeLargerSizeSpan = new RelativeSizeSpan(1.5f);
RelativeSizeSpan relativeSmallerSizeSpan = new RelativeSizeSpan(0.5f);
setSpanText(CONTENT + "Large", mRelativeSizeTextView, relativeLargerSizeSpan);
// Superscript text
SuperscriptSpan superscriptSpan = new SuperscriptSpan();
setSpanText(CONTENT + "Superscript & Small", mSuperscriptTextview, superscriptSpan, relativeSmallerSizeSpan);
// Subscript text
SubscriptSpan subscriptSpan = new SubscriptSpan();
setSpanText(CONTENT + "Subscript & Small", mSubscriptTextview, subscriptSpan, relativeSmallerSizeSpan);
// Url text
setUrlSpanText(CONTENT + "URL&Clickable", mUrlTextView, URL);
// Image text
mImageTextView.getViewTreeObserver()
.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Deprecated
@Override
public void onGlobalLayout() {
int height = mImageTextView.getHeight();
SpannableStringBuilder ssb =
addImageToText(SpannableStringApiActivity.this, R.drawable.ic_time, CONTENT + "Image", height);
mImageTextView.setText(ssb);
// must remove listener
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
mImageTextView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
mImageTextView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
}
});
}
private void setSpanText(String content, TextView textView, CharacterStyle span) {
SpannableStringBuilder ssb = new SpannableStringBuilder(content);
ssb.setSpan(span, START, END, 0);
textView.setText(ssb);
}
private void setSpanText(String content, TextView textView, CharacterStyle span1, CharacterStyle span2) {
SpannableStringBuilder ssb = new SpannableStringBuilder(content);
ssb.setSpan(span1, START, END, 0);
ssb.setSpan(span2, START, END, 0);
textView.setText(ssb);
}
private SpannableStringBuilder addImageToText(Context context, int drawableId, String text, int height) {
Drawable drawable = ContextCompat.getDrawable(context, drawableId);
int width = height * drawable.getIntrinsicWidth() / drawable.getIntrinsicHeight();
drawable.setBounds(0, 0, width, height);
SpannableStringBuilder ssb = new SpannableStringBuilder(" " + text);
ssb.setSpan(new ImageSpan(drawable), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
return ssb;
}
private void setUrlSpanText(String content, TextView textView, final String url) {
SpannableStringBuilder ssb = new SpannableStringBuilder(content);
ssb.setSpan(new ClickableSpan() {
@Override
public void onClick(View widget) {
Toast.makeText(SpannableStringApiActivity.this, url, Toast.LENGTH_LONG).show();
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(i);
}
}, START, END, 0);
textView.setText(ssb);
// setting the MovementMethod on the TextView that contains the span,
// otherwise onClick will not be called.
textView.setMovementMethod(LinkMovementMethod.getInstance());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment