Як встановити шрифт об’єкта Spannable зі спеціальним шрифтом


80

У мене є об’єкт 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.

EDIT:
Моя проблема полягає в тому, що я хочу встановити два різні користувацькі шрифти для подання тексту, тому я працюю з Spannable



1
@BenjaminDobell Питання не може бути дублікатом відповіді. Не посилайтеся на власну відповідь.
Чад Бінгем

Відповіді:


217

Це пізня відповідь, але вона допоможе іншим вирішити проблему.

Використовуйте такий код: (я використовую шрифт 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);

Результат:

введіть тут опис зображення


Клас 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);
}
}

Довідково


11
Хороший - хоча, якщо ви збираєтеся використовувати його з сімейством "", чому б взагалі не видалити параметр family з конструктора і просто викликати super ("");
Адам

@ imran-rana як я можу використовувати CustomTypefaceSpan?
mahdi pishguy

@Imran Rana, цей користувальницький клас видає помилку. "Цей клас реалізує Parcelable, але не надає поля CREATOR."
Крупс

@Krups Так, це не буде працювати, якщо CustomTypefaceSpan парцельовано та розпаковано ОС.
alexbirkett

Попередження: Цей клас реалізує, Parcelableале не надає CREATORполя.
Мір-Ісмаїлі

24

Створіть клас 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);

Ця відповідь базується на відповіді Імрана Рани, але не поширюється, TypefaceSpanа потім відключає її функціональність. CustomTypefaceSpanпоширюється MetricAffectingSpanбезпосередньо.

Ця відповідь поділяє дефект із відповіддю Імрана Рани. Проліт не парцельований. Тобто якщо ви зробите це (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, не будуть маршалізовані та немаршовані.


21

Нам не потрібно використовувати CustomTypefaceSpan. Ось рішення за допомогою 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);

3
StyleSpan не призначений для встановлення typeFace. Як зазначено в документації: Розмах, що дозволяє встановити стиль тексту, до якого він додається. Можливі стилі: Шрифт # NORMAL, Шрифт # BOLD, Шрифт # ITALIC та Шрифт # BOLD_ITALIC. Для даного коду буде встановлено значення ПІЛЬНОГО, не впливаючи на гарнітуру
kza

14

Якщо ви використовуєте Roboto, ви можете встановити інший TypefaceSpan у конструкторі

TypefaceSpan typefaceSpan = new TypefaceSpan("sans-serif-medium");

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

3

Новіша, простіша відповідь для> = 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

2

У котліні буде:

Перший крок , створіть цей клас

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

}

Другий крок ,

    val prefixText = SpannableString("I read and accept ")
    val prefixTextLen = prefixText.length

    prefixText.setSpan(
        CustomTypefaceSpan("", ResourcesCompat.getFont(context, R.font.gotham_bold)!!),
        0,
        prefixTextLen,
        0
    )

1

Спробуйте встановити Spannableдля вашого TextViewпершого, а потім, спробуйте призначити гарнітуру для вашого за TextViewдопомогою myTextView.setTypeface(tf);


На додаток до відповіді Серкана , я написав запис у блозі, де докладно про те, як користуватися інтервалами, можна дізнатися на blog.stylingandroid.com/archives/177 . Це не стосується спеціально налаштування гарнітур, саме тому я не публікував це як відповідь, але загалом охоплює деякі загальні підводні камені.
Mark Allison

Але це просто встановлює шрифт у всьому TextView? Це не проліт.
alexbirkett

0

Якщо ви використовуєте 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")
        }
    }
}

-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;
    }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.