在Android上使用自定义字体和自定义TextView

20

我需要开发一个应用程序,从中收到了一个特定的字体,该字体有许多文件,如FontName-Regular,FontName-BoldFontName-it。我需要在应用程序的所有文本视图中使用它。一开始我以为这是一项简单的任务。查询 Stack Overflow 发现了一个非常好的线程:这里

所以我首先尝试:

public static void overrideFonts(final Context context, final View v) {
    try {
        if (v instanceof ViewGroup) {
            ViewGroup vg = (ViewGroup) v;
            for (int i = 0; i < vg.getChildCount(); i++) {
                View child = vg.getChildAt(i);
                overrideFonts(context, child);
            }
        } else if (v instanceof TextView) {
            ((TextView)v).setTypeface(FONT_REGULAR);
        }
    } catch (Exception e) {
        e.printStackTrace();
        // ignore
    }
}

我在我的activity的onCreate方法中调用了这个方法。我的应用程序中的每个textView都显示该字体,我很高兴能够如此轻松地完成。直到我到达一个需要以粗体Styleandroid:textStyle="bold")的屏幕时,我意识到这种解决方案无法让我从资产中加载Font-Bold.ttf文件。

然后我进一步查看并在同一SO问题中找到了一个不错的自定义TextView实现:

public class MyTextView extends TextView {

    public MyTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    public MyTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public MyTextView(Context context) {
        super(context);
        init();
    }

    public void init() {

        Typeface tf = Typeface.createFromAsset(getContext().getAssets(), "font/chiller.ttf");
        setTypeface(tf ,1);

    }
    }

这看起来更好了。我的问题是:我如何在 init() 中检测我的控件是否设置为粗体,以便我可以分配请求的字体?

谢谢您的时间。

附:根据下面的示例,我已经更新了我的类:

public class MyTextView extends TextView {

    Typeface normalTypeface = Typeface.createFromAsset(getContext().getAssets(), Constants.FONT_REGULAR);
    Typeface boldTypeface = Typeface.createFromAsset(getContext().getAssets(),  Constants.FONT_BOLD);

    public MyTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public MyTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyTextView(Context context) {
        super(context);
    }

    public void setTypeface(Typeface tf, int style) {
        if (style == Typeface.BOLD) {
            super.setTypeface(boldTypeface/*, -1*/);
        } else {
            super.setTypeface(normalTypeface/*, -1*/);
        }
    }
}

我在调试时发现,应用程序进入了setTypeface方法,并似乎已经应用了粗体字,但在我的布局中看不到任何变化,文本视图没有变成粗体。无论我使用什么字体,在TextView中都没有做出任何更改,并显示默认的Android字体。我想知道为什么?

我在我的博客文章这里总结了所有内容,也许对某些人有帮助。


感谢您提供详细的问题阐述和优秀的博客文章!这对我非常有用。我也为同样的结果子类化了Button。我的唯一疑问是每次调用createFromAsset()是否效率更高?将字体加载一次并将其存储在您的应用类中,然后从MyTextView.setTypeface()访问这些字体是否更好呢? - Jarrod Smith
谢谢你的回复。我也考虑过这个问题,但没有测试它是否有效。它应该可以正常工作。无论如何,在屏幕上显示许多视图时,我没有看到任何性能惩罚。 - Alin
3个回答

27

TextView 的构造函数会调用 setTypeface(Typeface tf, int style) 方法,并将 style 参数从 XML 属性 android:textStyle 中检索出来。因此,如果您想拦截此调用以强制使用自己的字体,可以按照以下方式覆盖此方法:

public void setTypeface(Typeface tf, int style) {
    Typeface normalTypeface = Typeface.createFromAsset(getContext().getAssets(), "font/your_normal_font.ttf");
    Typeface boldTypeface = Typeface.createFromAsset(getContext().getAssets(), "font/your_bold_font.ttf");

    if (style == Typeface.BOLD) {
        super.setTypeface(boldTypeface/*, -1*/);
    } else {
        super.setTypeface(normalTypeface/*, -1*/);
    }
}

2
@Alin:问题在于setTypeface()在创建Typeface之前被构造函数调用!因此,将Typeface的创建移动到setTypeface()内部,现在它会正常工作! - Francesco Vadicamo
我尝试使用相同的解决方案,但不知何故却调用了setType(Typeface tf)而不是setTypeface(Typeface tf, int style),并且它被调用了两次。我不得不进行一些更改以确保粗体和斜体样式得到保留。无论如何,这给了我正确的方向,现在它可以工作了。谢谢。 - Ray

10

您可以使用我的CustomTextView,它允许您在assets文件夹中指定字体文件名称:

https://github.com/mafshin/CustomTextView

而且使用非常简单:

<com.my.app.CustomTextView
        xmlns:custom="http://schemas.android.com/apk/res/com.my.app"            
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Test text"
        android:id="@+id/testcustomview" 

        custom:fontAssetName="Politica XT.otf"
        />

2

我认为最好创建自己的字体包并将其导入到项目中,以便将来可以随时使用。

  package com.codeslips.utilities;  

  import android.content.Context; 
  import android.graphics.Typeface;
  import android.util.AttributeSet;
  import android.widget.TextView;  

  public class CustomTextView extends TextView {  

          public CustomTextView(Context context)
               { super(context); setFont(); }  

          public CustomTextView(Context context,AttributeSet set)
             { super(context,set); setFont(); } 

          public CustomTextView(Context context,AttributeSet set,int defaultStyle) 
             { super(context,set,defaultStyle); setFont(); } 

          private void setFont() { 

           Typeface typeface=Typeface.createFromAsset(getContext().getAssets(),"fonts/your-font.ttf"); 
           setTypeface(typeface); //function used to set font

             }  
          }

现在在你的XML文件中使用上述类来使用自定义字体。
    <com.codeslips.utilities.CustomTextView   
       android:layout_width="wrap_content" 
       android:layout_height="match_parent"
       android:text="Upload Image" 
       android:paddingTop="10sp"
       android:textSize="14sp"
       android:layout_weight="0.7"
       android:textColor="@android:color/white"/>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接