Festlegen der Spannable-Objektschriftart mit der benutzerdefinierten Schriftart

79

Ich habe ein Spannable-Objekt, dessen Schriftart ich durch eine benutzerdefinierte Schriftart festlegen möchte, die ich zuvor geladen habe.

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.

BEARBEITEN:
Mein Problem ist, dass ich zwei verschiedene benutzerdefinierte Schriftarten für die Textansicht festlegen möchte, damit ich mit dem Spannable arbeite

mohamedghonemi
quelle
Duplikat von stackoverflow.com/questions/4819049/…
Benjamin Dobell
1
@BenjaminDobell Eine Frage kann kein Duplikat einer Antwort sein. Verlinken Sie nicht auf Ihre eigene Antwort.
Chad Bingham

Antworten:

212

Dies ist eine späte Antwort, hilft aber anderen, das Problem zu lösen.

Verwenden Sie den folgenden Code: (Ich verwende die Schriftarten Bangla und 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);

Das Ergebnis ist:

Geben Sie hier die Bildbeschreibung ein


CustomTypefaceSpan Klasse:

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

Referenz

Imran Rana
quelle
11
Schön - wenn Sie es jedoch mit family "" verwenden möchten, entfernen Sie den Familienparameter ganz aus dem Konstruktor und rufen Sie einfach super ("") auf.
Adam
@ imran-rana wie kann ich verwenden CustomTypefaceSpan?
Mahdi Pishguy
@ Imran Rana, diese benutzerdefinierte Klasse gibt einen Flusenfehler aus. "Diese Klasse implementiert Parcelable, bietet jedoch kein CREATOR-Feld."
Krups
@Krups Ja, dies funktioniert nicht, wenn CustomTypefaceSpan vom Betriebssystem parzelliert und nicht parzelliert wird.
Alexbirkett
Warnung: Diese Klasse implementiert Parcelableein CREATORFeld , stellt es jedoch nicht bereit .
Mir-Ismaili
24

Erstellen Sie eine CustomTypefaceSpan-Klasse:

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

Verwendung auf die gleiche Weise wie das Android-Framework Klassen umfasst:

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

Diese Antwort basiert auf der Antwort von Imran Rana, erweitert TypefaceSpanund deaktiviert jedoch nicht die Funktionalität. CustomTypefaceSpanerstreckt sich MetricAffectingSpandirekt.

Diese Antwort teilt einen Fehler mit der Antwort von Imran Rana. Die Spanne ist nicht parzelliert. Dh wenn du das machst (kotlin):

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

Alle CustomTypefaceSpanObjekte, die spannableStringBuilderaktiviert sind, werden nicht gemarshallt und nicht gemarshallt.

alexbirkett
quelle
21

Wir müssen CustomTypefaceSpan nicht verwenden. Hier ist die Lösung mit 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);
Himanshu
quelle
2
StyleSpan soll das typeFace nicht festlegen. Wie in der Dokumentation angegeben: Spanne, mit der der Stil des angehängten Textes festgelegt werden kann. Mögliche Stile sind: Schrift # NORMAL, Schrift # BOLD, Schrift # ITALIC und Schrift # BOLD_ITALIC. Der angegebene Code würde die Spanne auf BOLD setzen, ohne die Schrift zu beeinflussen
kza
13

Wenn Sie Roboto verwenden, können Sie im Konstruktor ein anderes TypefaceSpan festlegen

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

textView.setSpan(typefaceSpan, indexStart, textLength, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
Renan Nery
quelle
2

In Kotlin wäre:

Erster Schritt , erstellen Sie diese Klasse

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

}

Zweiter Schritt ,

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

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

Neuere, einfachere Antwort für> = 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
Shalbert
quelle
1

Versuchen Sie Spannable, Ihre TextViewzuerst auf Ihre zu setzen , und versuchen Sie dann, die Schriftart Ihrer TextViewmit zuzuweisen myTextView.setTypeface(tf).

serkanozel
quelle
Neben Serkans Antwort habe ich unter blog.stylingandroid.com/archives/177 einen Blogeintrag geschrieben, in dem die Verwendung von Spans beschrieben wird . Es wird nicht speziell auf das Einstellen von Schriftarten eingegangen, weshalb ich dies nicht als Antwort gepostet habe, aber es behandelt einige der häufigsten Fallstricke bei Spans im Allgemeinen.
Mark Allison
Aber das setzt nur die Schrift in der gesamten TextView? Es ist keine Zeitspanne.
Alexbirkett
-1

Hier ist ein Beispiel, in dem str Ihre vollständige Zeichenfolge ist und boldString der Teil ist, den Sie fett machen müssen.

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;
    }
Max Droid
quelle