在runTime上添加字体资源

时间:2016-03-22 13:54:26

标签: java android fonts textview runtime

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

提前致谢。

1 个答案:

答案 0 :(得分:1)

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

首先,我想到了几件:

  1. 下载字体的东西
  2. 保存活动字体的东西
  3. 在字体不可用时处理它的某种方式(或者,更容易,在字体可用之前不要显示任何内容)
  4. 使用活动字体的自定义TextView
  5. 我要离开#1,因为我相信下载部分有点偏离实际使用字体的范围,并且有很多方法可以下载文件。

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

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

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

    它还引用了一个资产文件,以便在当前没有保存时​​将字体默认为

    现在我们需要一个自定义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部分。如果字体不可用,则您必须下载该字体。在下载时,您有两个选择:

    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,因为它相对容易:只需创建一个启动页面,并且不允许用户继续直到下载字体。

    同样,启动页面有点超出了这个范围,但希望这可以指出你如何完成任务的正确方向。