我需要使用特定的字体为我的整个应用程序。我有。ttf文件相同。 是否有可能将此设置为默认字体,在应用程序启动,然后在应用程序的其他地方使用它?当设置,我如何使用它在我的布局xml ?
当前回答
我写了一个类,将字体分配给当前视图层次结构中的视图,并基于当前字体属性(粗体,正常,如果你想,你可以添加其他样式):
public final class TypefaceAssigner {
public final Typeface DEFAULT;
public final Typeface DEFAULT_BOLD;
@Inject
public TypefaceAssigner(AssetManager assetManager) {
DEFAULT = Typeface.createFromAsset(assetManager, "TradeGothicLTCom.ttf");
DEFAULT_BOLD = Typeface.createFromAsset(assetManager, "TradeGothicLTCom-Bd2.ttf");
}
public void assignTypeface(View v) {
if (v instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) v).getChildCount(); i++) {
View view = ((ViewGroup) v).getChildAt(i);
if (view instanceof ViewGroup) {
setTypeface(view);
} else {
setTypeface(view);
}
}
} else {
setTypeface(v);
}
}
private void setTypeface(View view) {
if (view instanceof TextView) {
TextView textView = (TextView) view;
Typeface typeface = textView.getTypeface();
if (typeface != null && typeface.isBold()) {
textView.setTypeface(DEFAULT_BOLD);
} else {
textView.setTypeface(DEFAULT);
}
}
}
}
现在,在onViewCreated或onCreateView的所有片段中,在onCreate中的所有活动中,在getView或newView中的所有视图适配器中,只需调用:
typefaceAssigner.assignTypeface(view);
其他回答
我还想改进weston对API 21 Android 5.0的回答。
我的三星s5在使用默认字体时也遇到了同样的问题。(与其他字体的工作很好)
我设法使它工作通过设置字体(“sans”为例)在XML文件,为每个Textview或按钮
<TextView
android:layout_width="match_parent"
android:layout_height="39dp"
android:textColor="@color/abs__background_holo_light"
android:textSize="12sp"
android:gravity="bottom|center"
android:typeface="sans" />
在MyApplication类中:
public class MyApplication extends Application {
@Override
public void onCreate() {
TypefaceUtil.overrideFont(getApplicationContext(), "SANS_SERIF",
"fonts/my_font.ttf");
}
}
希望能有所帮助。
一个绝妙的解决方案可以在这里找到:https://coderwall.com/p/qxxmaa/android-use-a-custom-font-everywhere。
简单地从BaseActivity扩展活动并编写这些方法。此外,你应该更好地缓存字体如下所述:https://stackoverflow.com/a/16902532/2914140。
经过一番研究,我编写了适用于三星Galaxy Tab A (Android 5.0)的代码。weston和Roger Huang的使用代码以及https://stackoverflow.com/a/33236102/2914140。在联想TAB 2 A10-70L上也进行了测试,无法使用。 我在这里插入了一个“Comic Sans”字体,以便看到区别。
import android.content.Context;
import android.graphics.Typeface;
import android.os.Build;
import android.util.Log;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
public class FontsOverride {
private static final int BOLD = 1;
private static final int BOLD_ITALIC = 2;
private static final int ITALIC = 3;
private static final int LIGHT = 4;
private static final int CONDENSED = 5;
private static final int THIN = 6;
private static final int MEDIUM = 7;
private static final int REGULAR = 8;
private Context context;
public FontsOverride(Context context) {
this.context = context;
}
public void loadFonts() {
Map<String, Typeface> fontsMap = new HashMap<>();
fontsMap.put("sans-serif", getTypeface("comic.ttf", REGULAR));
fontsMap.put("sans-serif-bold", getTypeface("comic.ttf", BOLD));
fontsMap.put("sans-serif-italic", getTypeface("comic.ttf", ITALIC));
fontsMap.put("sans-serif-light", getTypeface("comic.ttf", LIGHT));
fontsMap.put("sans-serif-condensed", getTypeface("comic.ttf", CONDENSED));
fontsMap.put("sans-serif-thin", getTypeface("comic.ttf", THIN));
fontsMap.put("sans-serif-medium", getTypeface("comic.ttf", MEDIUM));
overrideFonts(fontsMap);
}
private void overrideFonts(Map<String, Typeface> typefaces) {
if (Build.VERSION.SDK_INT == 21) {
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", "Cannot set custom fonts");
}
} else {
try {
for (Map.Entry<String, Typeface> entry : typefaces.entrySet()) {
final Field staticField = Typeface.class.getDeclaredField(entry.getKey());
staticField.setAccessible(true);
staticField.set(null, entry.getValue());
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
private Typeface getTypeface(String fontFileName, int fontType) {
final Typeface tf = Typeface.createFromAsset(context.getAssets(), "fonts/" + fontFileName);
return Typeface.create(tf, fontType);
}
}
要在整个应用程序中运行代码,你应该在像application这样的类中编写如下代码:
new FontsOverride(this).loadFonts();
在“assets”里面创建一个文件夹“fonts”,把需要的字体放在那里。一个简单的说明可以在这里找到:https://stackoverflow.com/a/31697103/2914140。
联想设备还错误地获取了字体的值。在大多数情况下,它返回字体。NORMAL,有时为空。即使TextView是粗体(在xml文件布局)。看这里:TextView isBold总是返回正常。这样,屏幕上的文本总是使用常规字体,而不是粗体或斜体。所以我认为这是制作人的错误。
书法工作得很好,但它不适合我,因为它不支持字体家族的不同粗体(粗体、斜体等)。
所以我尝试了Fontain,它允许你定义自定义视图并应用自定义字体族。
为了使用Fontain,你应该在你的应用模块build.gradle中添加以下内容:
compile 'com.scopely:fontain:1.0.0'
然后,而不是使用常规的TextView,你应该使用FontTextView
使用大写和粗体内容的FontTextView示例:
<com.scopely.fontain.views.FontTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/black"
android:textColor="@android:color/white"
android:textSize="11dp"
android:gravity="center"
android:id="@+id/tv1"
app:font_family="myCustomFont"
app:caps_mode="characters"
app:font_weight="BOLD"/>
最后,谷歌意识到这个问题的严重性(将自定义字体应用到UI组件),他们为它设计了一个干净的解决方案。
首先,你需要更新到支持库26+(你可能还需要更新你的gradle{4.0+}, android studio),然后你可以创建一个新的资源文件夹称为字体。在这个文件夹中,您可以放置您的字体资源(.tff,…) 然后你需要覆盖默认的应用程序他们,并强制您的自定义字体:)
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:fontFamily">@font/my_custom_font</item>
</style>
注意:如果你想要支持API超过16的设备,你必须使用app命名空间而不是android!
总而言之:
选项1:使用反射来应用字体(结合weston和Roger Huang的回答):
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) {
if (isVersionGreaterOrEqualToLollipop()) {
Map<String, Typeface> newMap = new HashMap<String, Typeface>();
newMap.put("sans-serif", newTypeface);
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 staticField = Typeface.class.getDeclaredField(staticTypefaceFieldName);
staticField.setAccessible(true);
staticField.set(null, newTypeface);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
应用类使用:
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");
}
}
设置一个样式来强制字体应用程序宽(基于lovefish):
Pre-Lollipop:
<resources>
<style name="AppBaseTheme" parent="Theme.AppCompat.Light">
</style>
<!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<item name="android:typeface">monospace</item>
</style>
</resources>
棒棒糖(21火):
<resources>
<style name="AppBaseTheme" parent="Theme.AppCompat.Light">
</style>
<!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<item name="android:textAppearance">@style/CustomTextAppearance</item>
</style>
<style name="CustomTextAppearance">
<item name="android:typeface">monospace</item>
</style>
</resources>
选项2:子类每个和每个视图,你需要自定义字体,即。ListView, EditTextView, Button等(Palani的答案):
public class CustomFontView extends TextView {
public CustomFontView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public CustomFontView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CustomFontView(Context context) {
super(context);
init();
}
private void init() {
if (!isInEditMode()) {
Typeface tf = Typeface.createFromAsset(getContext().getAssets(), "Futura.ttf");
setTypeface(tf);
}
}
选项3:实现一个视图爬虫,遍历当前屏幕的视图层次结构:
变体#1(汤姆的回答):
public static final void setAppFont(ViewGroup mContainer, Typeface mFont, boolean reflect)
{
if (mContainer == null || mFont == null) return;
final int mCount = mContainer.getChildCount();
// Loop through all of the children.
for (int i = 0; i < mCount; ++i)
{
final View mChild = mContainer.getChildAt(i);
if (mChild instanceof TextView)
{
// Set the font if it is a TextView.
((TextView) mChild).setTypeface(mFont);
}
else if (mChild instanceof ViewGroup)
{
// Recursively attempt another ViewGroup.
setAppFont((ViewGroup) mChild, mFont);
}
else if (reflect)
{
try {
Method mSetTypeface = mChild.getClass().getMethod("setTypeface", Typeface.class);
mSetTypeface.invoke(mChild, mFont);
} catch (Exception e) { /* Do something... */ }
}
}
}
用法:
final ViewGroup mContainer = (ViewGroup) findViewById(
android.R.id.content).getRootView();
HomeActivity.setAppFont(mContainer, Typeface.createFromAsset(getAssets(),
"fonts/MyFont.ttf"));
变化# 2:https://coderwall.com/p/qxxmaa/android-use-a-custom-font-everywhere。
选项#4:使用称为书法的第三方自由。
就我个人而言,我会推荐选项4,因为它省去了很多麻烦。
推荐文章
- 使用什么api来绘制其他应用程序(如Facebook的Chat Heads)?
- Java中枚举的命名:单数还是复数?
- getDefaultSharedPreferences和getSharedPreferences的区别
- 如何模拟按钮点击使用代码?
- JavaBean和POJO之间的区别是什么?
- 注释在Java中如何使用,在哪里使用?
- 如何在Ubuntu下安装JDK 11 ?
- Android Webview给出net::ERR_CACHE_MISS消息
- Spring Boot -无法确定数据库类型为NONE的嵌入式数据库驱动程序类
- Parcelable遇到IOException写入序列化对象getactivity()
- 如何转换/解析从字符串到字符在java?
- 如何在Android中动态更改菜单项文本
- 如何将Base64字符串转换为位图图像,以显示在一个ImageView?
- 如何比较两个没有时间部分的日期?
- 如何在Java中找到给定类的所有子类?