How set Spannable object font with custom font
This is a late answer but will help others to solve the issue.
Use the following code:(I'm using Bangla and Tamil font)
TextView txt = (TextView) findViewById(R.id.custom_fonts); txt.setTextSize(30); Typeface font = Typeface.createFromAsset(getAssets(), "Akshar.ttf"); Typeface font2 = Typeface.createFromAsset(getAssets(), "bangla.ttf"); SpannableStringBuilder SS = new SpannableStringBuilder("আমারநல்வரவு"); SS.setSpan (new CustomTypefaceSpan("", font2), 0, 4,Spanned.SPAN_EXCLUSIVE_INCLUSIVE); SS.setSpan (new CustomTypefaceSpan("", font), 4, 11,Spanned.SPAN_EXCLUSIVE_INCLUSIVE); txt.setText(SS);
The outcome is:
CustomTypefaceSpan Class:
package my.app;import android.graphics.Paint;import android.graphics.Typeface;import android.text.TextPaint;import android.text.style.TypefaceSpan;public class CustomTypefaceSpan extends TypefaceSpan {private final Typeface newType;public CustomTypefaceSpan(String family, Typeface type) { super(family); newType = type;}@Overridepublic void updateDrawState(TextPaint ds) { applyCustomTypeFace(ds, newType);}@Overridepublic void updateMeasureState(TextPaint paint) { applyCustomTypeFace(paint, newType);}private static void applyCustomTypeFace(Paint paint, Typeface tf) { int oldStyle; Typeface old = paint.getTypeface(); if (old == null) { oldStyle = 0; } else { oldStyle = old.getStyle(); } int fake = oldStyle & ~tf.getStyle(); if ((fake & Typeface.BOLD) != 0) { paint.setFakeBoldText(true); } if ((fake & Typeface.ITALIC) != 0) { paint.setTextSkewX(-0.25f); } paint.setTypeface(tf);}}
Create a CustomTypefaceSpan class:
import android.graphics.Paint;import android.graphics.Typeface;import android.text.TextPaint;import android.text.style.MetricAffectingSpan;public class CustomTypefaceSpan extends MetricAffectingSpan { private final Typeface typeface; public CustomTypefaceSpan(Typeface typeface) { this.typeface = typeface; } @Override public void updateDrawState(TextPaint ds) { applyCustomTypeFace(ds, typeface); } @Override public void updateMeasureState(TextPaint paint) { applyCustomTypeFace(paint, typeface); } private static void applyCustomTypeFace(Paint paint, Typeface tf) { paint.setTypeface(tf); }}
Use in the same way as the Android framework spans classes:
TextView textView = (TextView) findViewById(R.id.custom_fonts); Typeface font = Typeface.createFromAsset(getAssets(), "Akshar.ttf"); Typeface font2 = Typeface.createFromAsset(getAssets(), "bangla.ttf"); SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder("আমারநல்வரவு"); spannableStringBuilder.setSpan (new CustomTypefaceSpan(font2), 0, 4,Spanned.SPAN_EXCLUSIVE_INCLUSIVE); spannableStringBuilder.setSpan (new CustomTypefaceSpan(font), 4, 11,Spanned.SPAN_EXCLUSIVE_INCLUSIVE); textView.setText(spannableStringBuilder);
This answer is based on Imran Rana's answer but does not extend TypefaceSpan
and then disable its functionality. CustomTypefaceSpan
extends MetricAffectingSpan
directly.
This answer shares a defect with Imran Rana's answer. The span is not parcelled. I.e if you do this (kotlin):
val parcel = Parcel.obtain() TextUtils.writeToParcel(spannableStringBuilder, parcel, 0) parcel.setDataPosition(0) val sequence = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel) parcel.recycle()
Any CustomTypefaceSpan
objects set on spannableStringBuilder
will not be marshalled and unmarshalled.
We don't need to use CustomTypefaceSpan. Here is the solution using StyleSpan.
/*** setCustomFontTypeSpan* @param context* @param source* @param startIndex* @param endIndex* @param font* @return*/public static SpannableString setCustomFontTypeSpan(Context context, String source, int startIndex, int endIndex, int font) { final SpannableString spannableString = new SpannableString(source); Typeface typeface = ResourcesCompat.getFont(context, font); spannableString.setSpan(new StyleSpan(typeface.getStyle()), startIndex,endIndex,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);return spannableString;}String source = "Hello world";SpannableString string = setCustomFontTypeSpan(context, source, 6, source.length(), R.font.open_sans_bold);textView.setText(string);