如何在棒棒糖中为整个应用程序设置自定义字体
how to set custom font for entire application in lollipop
我想为我的 app.I 中使用的所有文本视图设置自定义字体,代码如下
public static void overrideFont(Context context, String defaultFontNameToOverride, String customFontFileNameInAssets)
{
try
{
final Typeface customFontTypeface = Typeface.createFromAsset(context.getAssets(),customFontFileNameInAssets);
Field defaultFontTypefaceField = Typeface.class.getDeclaredField(defaultFontNameToOverride);
defaultFontTypefaceField.setAccessible (true);
defaultFontTypefaceField.set(null,customFontTypeface);
}
catch (Exception e)
{
Log.e("getMessage",e.getMessage());
e.printStackTrace();
//Log.e("Can not set custom font " + customFontFileNameInAssets + " instead of " + defaultFontNameToOverride);
}
}
调用方法如下
TypefaceUtil.overrideFont(this, "DEFAULT", getTypeFace());
TypefaceUtil.overrideFont(this, "MONOSPACE", getTypeFace());
TypefaceUtil.overrideFont(this, "SERIF", getTypeFace());
TypefaceUtil.overrideFont(this, "SANS_SERIF", getTypeFace());
此代码在 android 之前在 android 5 中有效,但在 lollipop 中不起作用。
我搜索了很多,但我没有找到任何东西。
我用 Calligraphy
做到了
在您的应用程序中 class 在 #onCreate() 方法中。
@Override
public void onCreate() {
super.onCreate();
CalligraphyConfig.initDefault(new CalligraphyConfig.Builder()
.setDefaultFontPath("fonts/Roboto-RobotoRegular.ttf")
.setFontAttrId(R.attr.fontPath)
.build()
);
//....
}
包装 Activity 上下文:
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase));
}
假设你选择的字体是serif-monospace
,那么你也应该像
一样实现
<style name="TextView" parent="android:Widget.TextView">
<item name="android:fontFamily">serif-monospace</item>
</style>
并像这样使用
<TextView
style="@style/TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
我通过覆盖应用程序默认字体来完成它:
创建 class FontsOverride:
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);
}
private 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();
}
}
}
创建一个 Application
Class 或将其添加到您当前的一个,如果您已经拥有:
public class AppController extends Application {
// add a folder named `fonts` under `assets` folder
// add theme here
String customFont1 = "fonts/IRANSans-Light-web.ttf";
String customFont2 = "fonts/font2.ttf";
String customFont3 = "fonts/font3.ttf";
String customFont4 = "fonts/font4.ttf";
@Override
public void onCreate() {
super.onCreate();
// override default fonts
FontsOverride.setDefaultFont(this, "DEFAULT", customFont1);
FontsOverride.setDefaultFont(this, "MONOSPACE", customFont2);
FontsOverride.setDefaultFont(this, "SERIF", customFont3);
FontsOverride.setDefaultFont(this, "SANS_SERIF", customFont4);
}
}
在 style
中为您的主题添加字体
<!-- Application theme -->
<style name="myTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:typeface">monospace</item>
</style>
最后,将其添加到 Application
标签中的 manifest
:
<application
android:name="path.AppController"
android:icon="@mipmap/ic_launcher"
android:theme="@style/myTheme"
android:label="@string/app_name">
(我已经测试过了,它也适用于`Lolipop)
我创建了一个递归函数并将其保存在我的 BaseActivity 中:
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);
}
}
if (v.getClass() == TextView.class) {
if (v.getTag() != null && v.getTag().toString().equalsIgnoreCase("bold")) {
((TextView) v).setTypeface(FontUtils.getFontBold(context));
} else {
((TextView) v).setTypeface(FontUtils.getFont(context));
}
}
if (v.getClass() == AppCompatTextView.class) {
if (v.getTag() != null && v.getTag().toString().equalsIgnoreCase("bold")) {
((TextView) v).setTypeface(FontUtils.getFontBold(context));
} else {
((TextView) v).setTypeface(FontUtils.getFont(context));
}
}
if (v.getClass() == Button.class) {
((Button) v).setTypeface(FontUtils.getFontBold(context));
}
if (v.getClass() == AppCompatButton.class) {
((Button) v).setTypeface(FontUtils.getFontBold(context));
}
if (v.getClass() == TextInputLayout.class) {
((TextInputLayout) v).setTypeface(FontUtils.getFontBold(context));
}
if (v.getClass() == TextInputEditText.class) {
((TextInputEditText) v).setTypeface(FontUtils.getFont(context));
}
if (v.getClass() == AppCompatEditText.class) {
((AppCompatEditText) v).setTypeface(FontUtils.getFont(context));
}
if (v.getClass() == EditText.class) {
if (v.getTag() != null && v.getTag().toString().equalsIgnoreCase("bold")) {
((EditText) v).setTypeface(FontUtils.getFontBold(context));
} else {
((EditText) v).setTypeface(FontUtils.getFont(context));
}
}
} catch (Exception e) {
Log.e("Font Exception", e.toString());
}
}
字体实用程序:
public abstract class FontUtils {
public static Typeface regular, bold;
public static Typeface getFont(Context appContext) {
if (regular == null) {
regular = Typeface.createFromAsset(appContext.getAssets(), "fonts/Lato-Regular.ttf");
}
return regular;
}
public static Typeface getFontBold(Context appContext) {
if (bold == null) {
bold = Typeface.createFromAsset(appContext.getAssets(), "fonts/Lato-Bold.ttf");
}
return bold;
}
}
您可以添加自己的案例,而且我使用 xml 中的标签来显示粗体和常规字体
android:tag="bold"
像这样在 BaseActivity 的 onCreate 中调用方法:
View contentView = this.findViewById(android.R.id.content);
overrideFonts(this, contentView);
确保在 activity 中的 setContentView 之后调用 super.OnCreate。
希望这对您有所帮助。
检查一下:Working with fonts。
从 I/O 2017 年起,您现在可以在 xml 中使用以下内容:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/lobster"/>
Google 添加了对 O 设备的支持,而且,我引用:
The Support Library 26.0 Beta provides support to the Fonts in XML feature on devices running Android API version 14 and higher.
我想为我的 app.I 中使用的所有文本视图设置自定义字体,代码如下
public static void overrideFont(Context context, String defaultFontNameToOverride, String customFontFileNameInAssets)
{
try
{
final Typeface customFontTypeface = Typeface.createFromAsset(context.getAssets(),customFontFileNameInAssets);
Field defaultFontTypefaceField = Typeface.class.getDeclaredField(defaultFontNameToOverride);
defaultFontTypefaceField.setAccessible (true);
defaultFontTypefaceField.set(null,customFontTypeface);
}
catch (Exception e)
{
Log.e("getMessage",e.getMessage());
e.printStackTrace();
//Log.e("Can not set custom font " + customFontFileNameInAssets + " instead of " + defaultFontNameToOverride);
}
}
调用方法如下
TypefaceUtil.overrideFont(this, "DEFAULT", getTypeFace());
TypefaceUtil.overrideFont(this, "MONOSPACE", getTypeFace());
TypefaceUtil.overrideFont(this, "SERIF", getTypeFace());
TypefaceUtil.overrideFont(this, "SANS_SERIF", getTypeFace());
此代码在 android 之前在 android 5 中有效,但在 lollipop 中不起作用。 我搜索了很多,但我没有找到任何东西。
我用 Calligraphy
做到了在您的应用程序中 class 在 #onCreate() 方法中。
@Override
public void onCreate() {
super.onCreate();
CalligraphyConfig.initDefault(new CalligraphyConfig.Builder()
.setDefaultFontPath("fonts/Roboto-RobotoRegular.ttf")
.setFontAttrId(R.attr.fontPath)
.build()
);
//....
}
包装 Activity 上下文:
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase));
}
假设你选择的字体是serif-monospace
,那么你也应该像
<style name="TextView" parent="android:Widget.TextView">
<item name="android:fontFamily">serif-monospace</item>
</style>
并像这样使用
<TextView
style="@style/TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
我通过覆盖应用程序默认字体来完成它:
创建 class FontsOverride:
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);
}
private 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();
}
}
}
创建一个 Application
Class 或将其添加到您当前的一个,如果您已经拥有:
public class AppController extends Application {
// add a folder named `fonts` under `assets` folder
// add theme here
String customFont1 = "fonts/IRANSans-Light-web.ttf";
String customFont2 = "fonts/font2.ttf";
String customFont3 = "fonts/font3.ttf";
String customFont4 = "fonts/font4.ttf";
@Override
public void onCreate() {
super.onCreate();
// override default fonts
FontsOverride.setDefaultFont(this, "DEFAULT", customFont1);
FontsOverride.setDefaultFont(this, "MONOSPACE", customFont2);
FontsOverride.setDefaultFont(this, "SERIF", customFont3);
FontsOverride.setDefaultFont(this, "SANS_SERIF", customFont4);
}
}
在 style
<!-- Application theme -->
<style name="myTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:typeface">monospace</item>
</style>
最后,将其添加到 Application
标签中的 manifest
:
<application
android:name="path.AppController"
android:icon="@mipmap/ic_launcher"
android:theme="@style/myTheme"
android:label="@string/app_name">
(我已经测试过了,它也适用于`Lolipop)
我创建了一个递归函数并将其保存在我的 BaseActivity 中:
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);
}
}
if (v.getClass() == TextView.class) {
if (v.getTag() != null && v.getTag().toString().equalsIgnoreCase("bold")) {
((TextView) v).setTypeface(FontUtils.getFontBold(context));
} else {
((TextView) v).setTypeface(FontUtils.getFont(context));
}
}
if (v.getClass() == AppCompatTextView.class) {
if (v.getTag() != null && v.getTag().toString().equalsIgnoreCase("bold")) {
((TextView) v).setTypeface(FontUtils.getFontBold(context));
} else {
((TextView) v).setTypeface(FontUtils.getFont(context));
}
}
if (v.getClass() == Button.class) {
((Button) v).setTypeface(FontUtils.getFontBold(context));
}
if (v.getClass() == AppCompatButton.class) {
((Button) v).setTypeface(FontUtils.getFontBold(context));
}
if (v.getClass() == TextInputLayout.class) {
((TextInputLayout) v).setTypeface(FontUtils.getFontBold(context));
}
if (v.getClass() == TextInputEditText.class) {
((TextInputEditText) v).setTypeface(FontUtils.getFont(context));
}
if (v.getClass() == AppCompatEditText.class) {
((AppCompatEditText) v).setTypeface(FontUtils.getFont(context));
}
if (v.getClass() == EditText.class) {
if (v.getTag() != null && v.getTag().toString().equalsIgnoreCase("bold")) {
((EditText) v).setTypeface(FontUtils.getFontBold(context));
} else {
((EditText) v).setTypeface(FontUtils.getFont(context));
}
}
} catch (Exception e) {
Log.e("Font Exception", e.toString());
}
}
字体实用程序:
public abstract class FontUtils {
public static Typeface regular, bold;
public static Typeface getFont(Context appContext) {
if (regular == null) {
regular = Typeface.createFromAsset(appContext.getAssets(), "fonts/Lato-Regular.ttf");
}
return regular;
}
public static Typeface getFontBold(Context appContext) {
if (bold == null) {
bold = Typeface.createFromAsset(appContext.getAssets(), "fonts/Lato-Bold.ttf");
}
return bold;
}
}
您可以添加自己的案例,而且我使用 xml 中的标签来显示粗体和常规字体
android:tag="bold"
像这样在 BaseActivity 的 onCreate 中调用方法:
View contentView = this.findViewById(android.R.id.content);
overrideFonts(this, contentView);
确保在 activity 中的 setContentView 之后调用 super.OnCreate。
希望这对您有所帮助。
检查一下:Working with fonts。
从 I/O 2017 年起,您现在可以在 xml 中使用以下内容:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/lobster"/>
Google 添加了对 O 设备的支持,而且,我引用:
The Support Library 26.0 Beta provides support to the Fonts in XML feature on devices running Android API version 14 and higher.