Skip to content

Instantly share code, notes, and snippets.

@janvde
Last active October 10, 2019 15:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save janvde/0f3a7d90107e6ed8507f1cc74a4fb9b0 to your computer and use it in GitHub Desktop.
Save janvde/0f3a7d90107e6ed8507f1cc74a4fb9b0 to your computer and use it in GitHub Desktop.
Make a substring of a string stylable
import android.content.Context;
import android.support.annotation.ColorRes;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.annotation.StyleRes;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.TextAppearanceSpan;
import android.view.View;
import android.widget.TextView;
/**
* Created by jan on 01/04/16.
* enables making a string stylable by giving multiple substrings a style
* capable of method chaining
*/
public class StyledString {
public interface OnSpanClickListener {
void onSpanClicked();
}
private SpannableStringBuilder fullStringBuilder;
private String fullString;
private Context context;
private int startingIndex;
private int endingIndex;
/**
* constructor for string
* @param context Context
* @param fullString full length string
*/
public StyledString(Context context, String fullString){
fullStringBuilder = new SpannableStringBuilder(fullString);
this.fullString = fullString;
this.context = context;
}
/**
* constructor for string resource
* @param context Context
* @param fullStringRes full length string resource
*/
public StyledString(Context context, @StringRes int fullStringRes){
String fullString = context.getString(fullStringRes);
fullStringBuilder = new SpannableStringBuilder(fullString);
this.fullString = fullString;
}
/**
* give a substring a styling
* @param subString substring of the fullstring
* @param textAppearance text style
* @return Styledstring
*/
public StyledString put(String subString, @StyleRes int textAppearance){
if(getStartEnd(subString)){
TextAppearanceSpan textAppearanceSpan = new TextAppearanceSpan(context, textAppearance);
fullStringBuilder.setSpan(textAppearanceSpan, startingIndex, endingIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return this;
}
/**
* give a substring a clickable link
* add this to textview: textView.setMovementMethod(LinkMovementMethod.getInstance());
*
* @param subString to make clickable
* @param spanClickListener listener to listen for cliks, can be null
* @return StyledString
*/
public StyledString putLink(String subString, @Nullable final OnSpanClickListener spanClickListener){
if(getStartEnd(subString)){
//clickable span with listener
ClickableSpan clickableSpan = new ClickableSpan() {
@Override
public void onClick(View widget) {
if (spanClickListener != null) {
spanClickListener.onSpanClicked();
}
}
};
fullStringBuilder.setSpan(clickableSpan,startingIndex, endingIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return this;
}
/**
* give a substring a color
* @param subString Substring
* @param colorRes color resource
* @return StyledString with color
*/
public StyledString putColor(String subString, @ColorRes int colorRes){
if(getStartEnd(subString)){
int color = ColorUtil.getColor(context, colorRes);
ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(color);
fullStringBuilder.setSpan(foregroundColorSpan, startingIndex, endingIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return this;
}
/**
* show directly in the given textview
* @param textView TextView
*/
public StyledString toView(TextView textView){
textView.setMovementMethod(LinkMovementMethod.getInstance()); //make links clickable
textView.setText(getStringBuilder(), TextView.BufferType.SPANNABLE);
return this;
}
public SpannableStringBuilder getStringBuilder(){
return fullStringBuilder;
}
/**
* calculate the beginning and end index of the substring
* @param subString String
* @return boolean true if index calculations are correctly done
*/
private boolean getStartEnd(String subString){
if(subString.length() > 0 && !subString.trim().equals("")) {
//for counting start/end indexes
startingIndex = fullString.indexOf(subString);
endingIndex = startingIndex + subString.length();
if(startingIndex < 0 || endingIndex <0){
return false;
}
return true;
}
return false;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment