사용자 지정 글꼴로 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.

편집 :
내 문제는 텍스트보기에 대해 두 가지 다른 사용자 정의 글꼴을 설정하여 Spannable로 작업하고 있다는 것입니다.



1
@BenjaminDobell 질문은 답변과 중복 될 수 없습니다. 자신의 답변에 연결하지 마십시오.
Chad Bingham

답변:


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
좋은 것입니다. ""패밀리와 함께 사용하려는 경우 생성자에서 패밀리 매개 변수를 모두 제거하고 super ( "")를 호출하십시오.
Adam

@ imran-rana 어떻게 사용할 수 CustomTypefaceSpan있습니까?
마흐디 pishguy

@Imran Rana,이 사용자 정의 클래스는 린트 오류를 ​​제공합니다. "이 클래스는 Parcelable을 구현하지만 CREATOR 필드는 제공하지 않습니다."
Krups

@Krups 예, CustomTypefaceSpan이 OS에 의해 분할되고 분할되지 않은 경우 작동하지 않습니다.
alexbirkett

경고 :이 클래스 ParcelableCREATOR필드를 구현 하지만 제공하지 않습니다 .
Mir-Ismaili

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

이 답변은 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는 마샬링되거나 마샬링되지 않습니다.


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를 설정하기위한 것이 아닙니다. documetation : Span에 설명 된대로 첨부 된 텍스트의 스타일을 설정할 수 있습니다. 가능한 스타일은 Typeface # NORMAL, Typeface # BOLD, Typeface # ITALIC 및 Typeface # BOLD_ITALIC입니다. 주어진 코드는 활자체에 영향을주지 않고 범위를 BOLD로 설정합니다
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

kotlin에서는 다음과 같습니다.

첫 번째 단계 ,이 클래스를 만듭니다.

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먼저 한 후, 당신에 서체를 할당하려고 TextViewmyTextView.setTypeface(tf);


Serkan의 답변에 더하여 blog.stylingandroid.com/archives/177 에서 스팬을 사용하는 방법을 자세히 설명하는 블로그 항목을 작성했습니다 . 서체 설정을 구체적으로 다루지 않으므로 답변으로 게시하지 않았지만 일반적으로 스팬에 대한 일반적인 함정 중 일부를 다루고 있습니다.
Mark Allison

그러나 이것은 전체 TextView의 서체를 설정합니까? 스팬이 아닙니다.
alexbirkett

0

당신이 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;
    }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.