How to set custom font for a whole application in Android?

匿名 (未验证) 提交于 2019-12-03 01:51:02

问题:

Is it possible to set a custom font in an Android application?

I tried what is posted here, but I don't know where my extends Application class is...

Any help?

EDIT:

I tried the following:

  • Add an assets folder and insert the font inside as seen here:

  • Add a new class that extends from Application

  • Call this new class from my AndroidManifest.xml.

  • I went to my style and added it.

MyApp.java:

public class MyApp extends Application {   @Override   public void onCreate() {      super.onCreate();     FontsOverride.setDefaultFont(this, "DEFAULT", "raleway_regular.ttf");     //  This FontsOverride comes from the example I posted above   }   } 

AndroidManifest.xml:

      .... 

styles.xml:

 

But my font is still not changning... any idea?

Then the MyApp class is called. But no effect on my fonts...

EDIT2: I realized that my buttons apply the custom font after I set a custom style for my buttons. Here is my custom button style:

And here is how it looks now:

So: my button is applying the style, but not the TextView. Any idea on why my custom font is not being applied for all items in application?

回答1:

Write a class

public class MyApp extends Application{ // Put the onCreate code as you obtained from the post link you reffered } 

now next thing is in AndroidManifest.xml for the application tag give name for your application class. In this case it is MyApp

 ... 

So whenever the App is opened , onCreate method of MyApp class would be invoked , and the font would be set.

Update Put font file under assets/fonts/your_font_file.ttf

Put this line under onCreate method of your application class(MyApp)

TypefaceUtil.overrideFont(getApplicationContext(), "SERIF", "fonts/your_font_file.ttf"); 

Source File for TypefaceUtil

public class TypefaceUtil {      /**      * Using reflection to override default typeface      * NOTICE: DO NOT FORGET TO SET TYPEFACE FOR APP THEME AS DEFAULT TYPEFACE WHICH WILL BE OVERRIDDEN      *      * @param context                    to work with assets      * @param defaultFontNameToOverride  for example "monospace"      * @param customFontFileNameInAssets file name of the font from assets      */     public static void overrideFont(Context context, String defaultFontNameToOverride, String customFontFileNameInAssets) {          final Typeface customFontTypeface = Typeface.createFromAsset(context.getAssets(), customFontFileNameInAssets);          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {             Map newMap = new HashMap();             newMap.put("serif", customFontTypeface);             try {                 final Field staticField = Typeface.class                         .getDeclaredField("sSystemFontMap");                 staticField.setAccessible(true);                 staticField.set(null, newMap);             } catch (NoSuchFieldException e) {                 e.printStackTrace();             } catch (IllegalAccessException e) {                 e.printStackTrace();             }         } else {             try {                 final Field defaultFontTypefaceField = Typeface.class.getDeclaredField(defaultFontNameToOverride);                 defaultFontTypefaceField.setAccessible(true);                 defaultFontTypefaceField.set(null, customFontTypeface);             } catch (Exception e) {                 Log.e(TypefaceUtil.class.getSimpleName(), "Can not set custom font " + customFontFileNameInAssets + " instead of " + defaultFontNameToOverride);             }         }     } } 

Now update your style.xml file

put the below line your style which is included for your activity in manifest file

  serif

Hope this helps



回答2:

There is a great library for custom fonts in android:Calligraphy
Here is a sample how to use it.

In Gradle you need to put this line into your app's build.gradle file:

        dependencies {             compile 'uk.co.chrisjenx:calligraphy:2.2.0'         } 

And then make a class that extends Application and write this code:

        public class App extends Application {             @Override             public void onCreate() {                 super.onCreate();                  CalligraphyConfig.initDefault(new CalligraphyConfig.Builder()                                 .setDefaultFontPath("your font path")                                 .setFontAttrId(R.attr.fontPath)                                 .build()                 );             }         }  

You should have made on assets/ a "New Directory" "fonts" (see below), so in that code "your font path" should be "fonts/SourceSansPro-Regular.ttf". (It's just "fonts..." not "/fonts.." or "assets..")

And in the activity class put this method before onCreate:

        @Override         protected void attachBaseContext(Context newBase) {             super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase));         } 

And the last thing your manifest file should look like this:

        

And it will change the whole activity to your font! it's simple and clean!

On Assets you should right-click New Directory, call it "fonts". In the finder put the .ttf font files in there.

Also dont forgot to add below two lines in attrs.xml,if you dont have attrs.xml file,create new file in values.xml

 


回答3:

Seems like you are using android:fontFamily instead of android:typeface in your styles.xml.

Try replacing

with



回答4:

If you follow the first topic, this should work : Here

Yes with reflection. This works (based on this answer):

(Note: this is a workaround due to lack of support for custom fonts, so if you want to change this situation please do star to up-vote the android issue here). Note: Do not leave "me too" comments on that issue, everyone who has stared it gets an email when you do that. So just "star" it please.

import java.lang.reflect.Field; import android.content.Context; import android.graphics.Typeface;  public final class FontsOverride {  public static void setDefaultFont(Context context,         String staticTypefaceFieldName, String fontAssetName) {     final Typeface regular = Typeface.createFromAsset(context.getAssets(),             fontAssetName);     replaceFont(staticTypefaceFieldName, regular); }  protected static void replaceFont(String staticTypefaceFieldName,         final Typeface newTypeface) {     try {         final Field staticField = Typeface.class                 .getDeclaredField(staticTypefaceFieldName);         staticField.setAccessible(true);         staticField.set(null, newTypeface);     } catch (NoSuchFieldException e) {         e.printStackTrace();     } catch (IllegalAccessException e) {         e.printStackTrace();     } } } 

You then need to overload the few default fonts, for example in an application class:

public final class Application extends android.app.Application {     @Override     public void onCreate() {         super.onCreate();         FontsOverride.setDefaultFont(this, "DEFAULT", "MyFontAsset.ttf");         FontsOverride.setDefaultFont(this, "MONOSPACE", "MyFontAsset2.ttf");         FontsOverride.setDefaultFont(this, "SERIF", "MyFontAsset3.ttf");         FontsOverride.setDefaultFont(this, "SANS_SERIF", "MyFontAsset4.ttf");     } } 

Or course if you are using the same font file, you can improve on this to load it just once.

However I tend to just override one, say "MONOSPACE", then set up a style to force that font typeface application wide:

API 21 Android 5.0

I've investigated the reports in the comments that it doesn't work and it appears to be incompatible with the theme android:Theme.Material.Light.

If that theme is not important to you, use an older theme, e.g.:



回答5:

All I did was:

1: Added "new resource directory" to the RES folder, Selected RESOURCE TYPE as "font" from the drop-down given, named the new directory "font" and saved.

2: Added my "custom_font.ttf" to the FONT folder just created.

3: Added my custom font in the application base theme in STYLES.XML

DONE.



回答6:

First, make a new class that overrides whatever View you want to customize. (e.g. want a Button with a custom typeface? Extend Button). For example:

public class CustomButton extends Button {     private final static int ROBOTO = 0;     private final static int ROBOTO_CONDENSED = 1;      public CustomButton(Context context) {         super(context);     }      public CustomButton(Context context, AttributeSet attrs) {         super(context, attrs);         parseAttributes(context, attrs); //I'll explain this method later     }      public CustomButton(Context context, AttributeSet attrs, int defStyle) {         super(context, attrs, defStyle);         parseAttributes(context, attrs);     } } 

Now, if you don't have one, add an XML document under res/values/attrs.xml, and add:

Okay, so with that out of the way, let's get back to the parseAttributes() method from earlier:

private void parseAttributes(Context context, AttributeSet attrs) {     TypedArray values = context.obtainStyledAttributes(attrs, R.styleable.CustomButton);      //The value 0 is a default, but shouldn't ever be used since the attr is an enum     int typeface = values.getInt(R.styleable.CustomButton_typeface, 0);      switch(typeface) {         case ROBOTO: default:             //You can instantiate your typeface anywhere, I would suggest as a              //singleton somewhere to avoid unnecessary copies             setTypeface(roboto);              break;         case ROBOTO_CONDENSED:             setTypeface(robotoCondensed);             break;     }      values.recycle(); } 

Now you're all set. You can add more attributes for about anything (you could add another one for typefaceStyle -- bold, italic, etc.) but now let's see how to use it:

The xmlns:custom line can really be anything, but the convention is what's shown above. What matters is that it is unique, and that's why the package name is used. Now you just use the custom: prefix for your attributes, and the android: prefix for android attributes.

One last thing: if you want to use this in a style (res/values/styles.xml), you should not add the xmlns:custom line. Just reference the name of the attribute with no prefix:



回答7:

I have tried font override too but at the end it's not a reliable solution, sadly overriding fonts take more than that. You can either wait for Android O with custom font to comes out or use a third party library.

The last solution that I came across was this library Caligraphy , which was easy to initiate and let you use as many font as you want. While checking its source code I understood why just overriding fonts won't work so even if you don't plan to use it I recommend reading through it once..

Good luck



回答8:

Try below code, it works for me, Hope it'll help you too.

public class BaseActivity extends AppCompatActivity {  private Typeface typeace; @Override protected void onCreate(Bundle savedInstanceState) {     // TODO Auto-generated method stub     super.onCreate(savedInstanceState);     typeace = Typeface.createFromAsset(getAssets(), getResources().getString(R.string.font_name)); }  @Override protected void onStart() {     // TODO Auto-generated method stub     super.onStart();     overrideFonts(this,getWindow().getDecorView()); }  private void overrideFonts(final Context context, final View v) {     try {         if (v instanceof ViewGroup) {             ViewGroup vg = (ViewGroup) v;             for (int i = 0; i 

Now extend this BaseActivity to any of your Activity or you can create same class for fragment if you are using.

Note:- If you want to set some of the view different typeface then you have to set that programmatically as below

private Typeface typeface; typeface = Typeface.createFromAsset(getAssets(), getResources().getString(R.string.font_name_bold)); tvUserName.setTypeface(typeface); 

So give it a try and let me know, If I could help you further



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!