问题
I\'m using the Roboto light font in my app. To set the font I\'ve to add the android:fontFamily=\"sans-serif-light\"
to every view. Is there any way to declare the Roboto font as default font family to entire app? I\'ve tried like this but it didn\'t seem to work.
<style name=\"AppBaseTheme\" parent=\"android:Theme.Light\"></style>
<style name=\"AppTheme\" parent=\"AppBaseTheme\">
<item name=\"android:fontFamily\">sans-serif-light</item>
</style>
回答1:
The answer is yes.
Global Roboto light for TextView
and Button
classes:
<style name="AppTheme" parent="AppBaseTheme">
<item name="android:textViewStyle">@style/RobotoTextViewStyle</item>
<item name="android:buttonStyle">@style/RobotoButtonStyle</item>
</style>
<style name="RobotoTextViewStyle" parent="android:Widget.TextView">
<item name="android:fontFamily">sans-serif-light</item>
</style>
<style name="RobotoButtonStyle" parent="android:Widget.Holo.Button">
<item name="android:fontFamily">sans-serif-light</item>
</style>
Just select the style you want from list themes.xml, then create your custom style based on the original one. At the end, apply the style as the theme of the application.
<application
android:theme="@style/AppTheme" >
</application>
It will work only with built-in fonts like Roboto, but that was the question. For custom fonts (loaded from assets for example) this method will not work.
EDIT 08/13/15
If you're using AppCompat themes, remember to remove android:
prefix. For example:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:textViewStyle">@style/RobotoTextViewStyle</item>
<item name="buttonStyle">@style/RobotoButtonStyle</item>
</style>
Note the buttonStyle
doesn't contain android:
prefix, but textViewStyle
must contain it.
回答2:
With the release of Android Oreo you can use the support library to reach this goal.
- Check in your app build.gradle if you have the support library >= 26.0.0
- Add "font" folder to your resources folder and add your fonts there
Reference your default font family in your app main style:
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:fontFamily">@font/your_font</item> <item name="fontFamily">@font/your_font</item> <!-- target android sdk versions < 26 and > 14 if theme other than AppCompat --> </style>
Check https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html for more detailed information.
回答3:
READ UPDATES BELOW
I had the same issue with embedding a new font and finally got it to work with extending the TextView and set the typefont inside.
public class YourTextView extends TextView {
public YourTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public YourTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public YourTextView(Context context) {
super(context);
init();
}
private void init() {
Typeface tf = Typeface.createFromAsset(context.getAssets(),
"fonts/helveticaneue.ttf");
setTypeface(tf);
}
}
You have to change the TextView Elements later to from to in every element. And if you use the UI-Creator in Eclipse, sometimes he doesn't show the TextViews right. Was the only thing which work for me...
UPDATE
Nowadays I'm using reflection to change typefaces in whole application without extending TextViews. Check out this SO post
UPDATE 2
Starting with API Level 26 and available in 'support library' you can use
android:fontFamily="@font/embeddedfont"
Further information: Fonts in XML
回答4:
To change your app font follow the following steps:
- Inside
res
directory create new directory and call itfont
. - Insert your font .ttf/.otf inside the font folder, Make sure the font name is lower case letters and underscore only.
- Inside
res
->values
->styles.xml
inside<resources>
-><style>
add your font<item name="android:fontFamily">@font/font_name</item>
.
Now all your app text shuld be in the fount that you add.
回答5:
Not talk about performance, for custom font you can have a recursive method loop through all the views and set typeface if it's a TextView:
public class Font {
public static void setAllTextView(ViewGroup parent) {
for (int i = parent.getChildCount() - 1; i >= 0; i--) {
final View child = parent.getChildAt(i);
if (child instanceof ViewGroup) {
setAllTextView((ViewGroup) child);
} else if (child instanceof TextView) {
((TextView) child).setTypeface(getFont());
}
}
}
public static Typeface getFont() {
return Typeface.createFromAsset(YourApplicationContext.getInstance().getAssets(), "fonts/whateverfont.ttf");
}
}
In all your activity, pass current ViewGroup to it after setContentView and it's done:
ViewGroup group = (ViewGroup) getWindow().getDecorView().findViewById(android.R.id.content);
Font.setAllTextView(group);
For fragment you can do something similar.
回答6:
Another way to do this for the whole app is using reflection based on this answer
public class TypefaceUtil {
/**
* Using reflection to override default typefaces
* NOTICE: DO NOT FORGET TO SET TYPEFACE FOR APP THEME AS DEFAULT TYPEFACE WHICH WILL BE
* OVERRIDDEN
*
* @param typefaces map of fonts to replace
*/
public static void overrideFonts(Map<String, Typeface> typefaces) {
try {
final Field field = Typeface.class.getDeclaredField("sSystemFontMap");
field.setAccessible(true);
Map<String, Typeface> oldFonts = (Map<String, Typeface>) field.get(null);
if (oldFonts != null) {
oldFonts.putAll(typefaces);
} else {
oldFonts = typefaces;
}
field.set(null, oldFonts);
field.setAccessible(false);
} catch (Exception e) {
Log.e("TypefaceUtil", "Can not set custom fonts");
}
}
public static Typeface getTypeface(int fontType, Context context) {
// here you can load the Typeface from asset or use default ones
switch (fontType) {
case BOLD:
return Typeface.create(SANS_SERIF, Typeface.BOLD);
case ITALIC:
return Typeface.create(SANS_SERIF, Typeface.ITALIC);
case BOLD_ITALIC:
return Typeface.create(SANS_SERIF, Typeface.BOLD_ITALIC);
case LIGHT:
return Typeface.create(SANS_SERIF_LIGHT, Typeface.NORMAL);
case CONDENSED:
return Typeface.create(SANS_SERIF_CONDENSED, Typeface.NORMAL);
case THIN:
return Typeface.create(SANS_SERIF_MEDIUM, Typeface.NORMAL);
case MEDIUM:
return Typeface.create(SANS_SERIF_THIN, Typeface.NORMAL);
case REGULAR:
default:
return Typeface.create(SANS_SERIF, Typeface.NORMAL);
}
}
}
then whenever you want to override the fonts you can just call the method and give it a map of typefaces as follows:
Typeface regular = TypefaceUtil.getTypeface(REGULAR, context);
Typeface light = TypefaceUtil.getTypeface(REGULAR, context);
Typeface condensed = TypefaceUtil.getTypeface(CONDENSED, context);
Typeface thin = TypefaceUtil.getTypeface(THIN, context);
Typeface medium = TypefaceUtil.getTypeface(MEDIUM, context);
Map<String, Typeface> fonts = new HashMap<>();
fonts.put("sans-serif", regular);
fonts.put("sans-serif-light", light);
fonts.put("sans-serif-condensed", condensed);
fonts.put("sans-serif-thin", thin);
fonts.put("sans-serif-medium", medium);
TypefaceUtil.overrideFonts(fonts);
for full example check
This only works for Android SDK 21 and above for earlier versions check the full example
回答7:
Just use this lib compile it in your grade file
complie'me.anwarshahriar:calligrapher:1.0'
and use it in the onCreate method in the main activity
Calligrapher calligrapher = new Calligrapher(this);
calligrapher.setFont(this, "yourCustomFontHere.ttf", true);
This is the most elegant super fast way to do that.
回答8:
This is work for my project, source https://gist.github.com/artem-zinnatullin/7749076
Create fonts directory inside Asset Folder and then copy your custom font to fonts directory, example I am using trebuchet.ttf;
Create a class TypefaceUtil.java;
import android.content.Context;
import android.graphics.Typeface;
import android.util.Log;
import java.lang.reflect.Field;
public class TypefaceUtil {
public static void overrideFont(Context context, String defaultFontNameToOverride, String customFontFileNameInAssets) {
try {
final Typeface customFontTypeface = Typeface.createFromAsset(context.getAssets(), customFontFileNameInAssets);
final Field defaultFontTypefaceField = Typeface.class.getDeclaredField(defaultFontNameToOverride);
defaultFontTypefaceField.setAccessible(true);
defaultFontTypefaceField.set(null, customFontTypeface);
} catch (Exception e) {
}
}
}
Edit theme in styles.xml add below
<item name="android:typeface">serif</item>
Example in My styles.xml
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:typeface">serif</item><!-- Add here -->
</style>
<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowActionBarOverlay">true</item>
<item name="android:windowFullscreen">true</item>
</style>
</resources>
Finally, in Activity or Fragment onCreate call TypefaceUtil.java
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TypefaceUtil.overrideFont(getContext(), "SERIF", "fonts/trebuchet.ttf");
}
回答9:
Android does not provide much in the way of support for applying fonts across the whole app (see this issue). You have 4 options to set the font for the entire app:
- Option1: Apply reflection to change the system font
- Option2: Create and subclass custom View classes for each View that needs a custom font
- Option3: Implement a View Crawler which traverses the view hierarchy for the current screen
- Option4: Use a 3rd party library.
Details of these options can be found here.
回答10:
I know this question is quite old, but I have found a nice solution. Basically, you pass a container layout to this function, and it will apply the font to all supported views, and recursively cicle in child layouts:
public static void setFont(ViewGroup layout)
{
final int childcount = layout.getChildCount();
for (int i = 0; i < childcount; i++)
{
// Get the view
View v = layout.getChildAt(i);
// Apply the font to a possible TextView
try {
((TextView) v).setTypeface(MY_CUSTOM_FONT);
continue;
}
catch (Exception e) { }
// Apply the font to a possible EditText
try {
((TextView) v).setTypeface(MY_CUSTOM_FONT);
continue;
}
catch (Exception e) { }
// Recursively cicle into a possible child layout
try {
ViewGroup vg = (ViewGroup) v;
Utility.setFont(vg);
continue;
}
catch (Exception e) { }
}
}
回答11:
to merely set typeface of app to normal
, sans
, serif
or monospace
(not to a custom font!), you can do this.
define a theme and set the android:typeface
attribute to the typeface you want to use in styles.xml
:
<resources>
<!-- custom normal activity theme -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<!-- other elements -->
<item name="android:typeface">monospace</item>
</style>
</resources>
apply the theme to the whole app in the AndroidManifest.xml
file:
<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
<application
android:theme="@style/AppTheme" >
</application>
</manifest>
android reference
回答12:
Try this library, its lightweight and easy to implement
https://github.com/sunnag7/FontStyler
<com.sunnag.fontstyler.FontStylerView
android:textStyle="bold"
android:text="@string/about_us"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="8dp"
app:fontName="Lato-Bold"
android:textSize="18sp"
android:id="@+id/textView64" />
回答13:
Add this line of code in your res/value/styles.xml
<item name="android:fontFamily">@font/circular_medium</item>
the entire style will look like that
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:fontFamily">@font/circular_medium</item>
</style>
change "circular_medium" to your own font name..
回答14:
The answer is no, you can't. See Is it possible to set a custom font for entire of application? for more information.
There are workarounds, but nothing in the lines of "one single line of code here and all my fonts will be this instead of that".
(I kind of thank Google -and Apple- for that). Custom fonts have a place, but making them easy to replace app wide, would have created an entire world of Comic Sans applications)
来源:https://stackoverflow.com/questions/16404820/how-to-set-default-font-family-for-entire-android-app