如何使用自定义字体设置Spannable对象字体

时间:2011-07-07 14:34:34

标签: android android-fonts spannable

我有Spannable对象,我想通过之前加载的自定义字体设置其字体。

Typeface tf = Typeface.createFromAsset(getAssets(), "fonts/font_Name.ttf");
Spannable span1 = /*Spannable Item*/;

/// I want to set span1 to have tf font face???
/// Here where I want help.

编辑:
我的问题是我想为文本视图设置两种不同的自定义字体,所以我正在使用Spannable

10 个答案:

答案 0 :(得分:181)

这是一个迟到的答案,但会帮助其他人解决问题。

使用以下代码:(我使用的是Bangla和Tamil字体)

  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);

结果是:

enter image description here


CustomTypefaceSpan类:

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;
}

@Override
public void updateDrawState(TextPaint ds) {
    applyCustomTypeFace(ds, newType);
}

@Override
public 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);
}
}

Reference

答案 1 :(得分:12)

创建CustomTypefaceSpan类:

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);
    }
}

以与Android框架跨越类相同的方式使用:

    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);

此答案基于Imran Rana的答案,但未扩展TypefaceSpan,然后禁用其功能。 CustomTypefaceSpan直接延长MetricAffectingSpan

这个答案与Imran Rana的回答有一个共同点。跨度不是分区。即如果你这样做(kotlin):

    val parcel = Parcel.obtain()
    TextUtils.writeToParcel(spannableStringBuilder, parcel, 0)
    parcel.setDataPosition(0)
    val sequence = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel)
    parcel.recycle()

CustomTypefaceSpan上设置的任何spannableStringBuilder个对象都不会被编组和解组。

答案 2 :(得分:9)

如果您使用的是Roboto,则可以在构造函数

中设置不同的TypefaceSpan
TypefaceSpan typefaceSpan = new TypefaceSpan("sans-serif-medium");

textView.setSpan(typefaceSpan, indexStart, textLength, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

答案 3 :(得分:9)

我们不需要使用CustomTypefaceSpan。这是解决方案。

{{1}}

答案 4 :(得分:4)

如果您使用的Android KTX buildSpannable{...}

我建议这一个。

inline fun SpannableStringBuilder.font(typeface: Typeface? = null, builderAction: SpannableStringBuilder.() -> Unit) =
    inSpans(StyleSpan(typeface?.style ?: Typeface.DEFAULT.style), builderAction = builderAction)

用法

binding.title.text = buildSpannedString {
    color(getColor(R.color.main_mint)) {
        font(getFont(R.font.notosans_medium)) {
            append("colored and typefaced")
        }
    }
}

答案 5 :(得分:2)

在科特林将是:

第一步,创建此类

filterTuples :: [(Int, Int)] -> [(Int,Int)]
filterTuples [] = []
filterTuples (x:xs) = x:filterTuples(concat ((fst temp) : [filter (\z -> fst z /= del) (snd temp)]))
    where del = fst (head (snd temp))
          temp = break (\y -> (snd y == fst x)) xs 

第二步

class CustomTypefaceSpan(family: String?, private val newType: Typeface) :
  TypefaceSpan(family) {
  override fun updateDrawState(ds: TextPaint) {
      applyCustomTypeFace(ds, newType)
  }

  override fun updateMeasureState(paint: TextPaint) {
      applyCustomTypeFace(paint, newType)
  }

  companion object {
      private fun applyCustomTypeFace(paint: Paint, tf: Typeface) {
          val oldStyle: Int
          val old = paint.typeface
          oldStyle = old?.style ?: 0
          val fake = oldStyle and tf.style.inv()
          if (fake and Typeface.BOLD != 0) {
              paint.isFakeBoldText = true
          }
          if (fake and Typeface.ITALIC != 0) {
              paint.textSkewX = -0.25f
          }
          paint.typeface = tf
      }
  }

}

答案 6 :(得分:2)

> = API 28的更新,更简单的答案

val myTypeface = Typeface.create(ResourcesCompat.getFont(context, R.font.acme), Typeface.NORMAL)
val string = SpannableString("Text with typeface span.")
string.setSpan(TypefaceSpan(myTypeface), 10, 18, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
string.setSpan(TypefaceSpan("monospace"), 19, 22, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)

textView.text = string

答案 7 :(得分:1)

首先尝试将Spannable设置为TextView,然后尝试使用TextViewmyTextView.setTypeface(tf)分配给{{1}};

答案 8 :(得分:1)

我想做同样的事情,但我发现我需要使用 TypefaceSpan。问题是采用 Typeface 的构造函数仅在 API 级别 28 中添加。所以我找到的解决方法是执行以下操作:

val spannable = SpannableString("My String")
spannable.setSpan(object : TypefaceSpan(null) {
    override fun updateDrawState(ds: TextPaint) {
        ds.typeface = Typeface.create(ResourcesCompat.getFont(context, R.font.my_font), Typeface.NORMAL) // To change according to your need
    }
}, start, end, Spannable.SPAN_INCLUSIVE_EXCLUSIVE) // To change according to your need
myTextView.setText(spannable)

答案 9 :(得分:-1)

这是一个例子,其中str是你的完整字符串,boldString是你需要加粗的部分。

public static SpannableString getTextStyleSpan(String str, String boldString) {

        SpannableString formated = new SpannableString(str);

        int start1 = str.indexOf(boldString);
        int end1 = start1 + colorString1.length();

        formated.setSpan(new android.text.style.StyleSpan(android.graphics.Typeface.BOLD), start1, end1, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
        return formated;
    }