在运行时添加字体资源

Add font ressource on runTime

我正在尝试向我的应用动态添加字体。我想根据我的服务器指示的字体在 运行 时间更改我的应用程序的每个 TextView 的字体。有没有办法下载字体(ttf 文件或其他)并在 运行 时间使用它?

提前致谢。

超级酷的问题,所以我要试一试并为您指明正确的方向,因为我绝对认为这是可能的。

首先,我想到了以下几点:

  1. 下载字体的东西
  2. 用来存放活动字体的东西
  3. 当字体不可用时处理它的一些方法(或者,更简单的是,在字体可用之前不显示任何内容)
  4. 使用活动字体的自定义 TextView

我将把第 1 留给你,因为我认为下载部分有点超出了如何实际使用字体的范围,而且有很多方法可以下载文件。

对于 #2,我们可以使用单例来保存对活动 TypeFace 的引用(这样我们就不会为每个想要使用它的视图重新创建它):

public class FontHolder {
    private static FontHolder instance;
    public static FontHolder getInstance(Context context){
        if(instance == null) 
            instance = new FontHolder(context);

        return instance;
    }

    private static final String PREF_TABLE = "font_prefs"
    private static final String ACTIVE_FONT_PREF = "active_font_file";
    private static final String DEFAULT_PREF_ASSET = "fonts/default_font.ttf";

    private Context context;
    private Typeface activeTypeFace;

    protected FontHolder(Context context){
        this.context = context.getApplicationContext();

        String activeFilePath = getSavedActiveFont();
        this.activeTypeFace = activeFilePath == null
                ? Typeface.createFromAssets(context.getResources().getAssets()
                : Typeface.createFromFile(new File(activeFilePath));
    }

    private String getSavedActiveFont(){
        return context.getSharedPreferences(PREF_TABLE, 0)
            .getString(ACTIVE_FONT_PREF, null);
    }

    public void setActiveFont(File activeFontFile){
        this.activeFont = Typeface.createFromFile(activeFontFile);

        context.getSharedPreferences(PREF_TABLE, 0)
            .edit()
            .putString(ACTIVE_FONT_PREF, activeFontFile.getAbsolutePath())
            .commit();
    }

    public Typeface getActiveFont(){
        return activeFont;
    }
}

如您所见,使用它我们可以轻松地更改实例中的活动字体,并在首选项中存储对该文件的引用以在会话之外持续存在。如果您想添加不同的变体(例如粗体、斜体等),您可以修改模板。

它还有一个资产文件的引用,默认字体为当前保存 none 时的字体。

现在我们需要一个自定义 TextView 来使用这个 TypeFace:

public class DynamicFontTextView extends TextView {

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

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

    public DynamicFontTextView(Context context) {
        super(context);
        updateActiveFont();
    }

    @Override
    public void setTypeface(Typeface tf, int style) {
        // if(style == Typeface.BOLD) <-- Something for later
        super.setTypeface(FontHolder.getInstance().getActiveFont());
    }

    public void updateActiveFont(){
        super.setTypeface(FontHolder.getInstance().getActiveFont());
    }
}

现在,在您的 XML 文件中,您可以将 DynamicFontTextView 与以下内容一起使用:

<com.package.DynamicFontTextView
 ....
 />

现在,回到第 3 部分。如果字体不可用,您将不得不下载它。下载时,您有 2 个选择:

A. Prevent them from getting to a screen where the custom font would ever be used.
B. Render with a default font, and then update the Views once the font is available

在这种情况下,让我们选择 A,因为它相对简单:只需创建一个初始页面,并且在字体下载完成之前不允许用户继续。

同样,初始页面有点超出了本文的范围,但希望这会为您指明正确的方向,帮助您完成任务。