您的位置:首页 > 移动开发

Android引入外部字体更改APP字体

2016-12-13 09:50 459 查看
由于最近的项目需要改变字体,所以用到了现在的方法,下面的总结是从网上整理出来的。但是还是比较好用的。希望能帮助大家省些时间。

public
class Y_fonts
extends Activity {
/**
Called when the activity is first created. */
@Override
public
void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
/*
* 必须事先在assets底下创建一fonts文件夹 并放入要使用的字体文件(.ttf)
* 并提供相对路径给creatFromAsset()来创建Typeface对象
*/
Typeface fontFace = Typeface.createFromAsset(getAssets(),
"fonts/STXINGKA.TTF");
//
字体文件必须是true type font的格式(ttf);
// 当使用外部字体却又发现字体没有变化的时候(以 Droid Sans代替),通常是因为
// 这个字体android没有支持,而非你的程序发生了错误

TextView text = (TextView) findViewById(R.id.ttf);
text.setTypeface(fontFace);
}
}

Android开发的时候,一些软件会要求一些特殊字体,我们需要引入外部的ttf格式的字体到程序中,具体操作步骤为:
安卓应用程序的目录assets中新建fonts目录,将我们需要使用的ttf字体文件复制进去,然后代码:
// 得到TextView控件对象TextView textView = (TextView)
findViewById(R.id.custom);// 将字体文件保存在assets/fonts/目录下,www.linuxidc.com创建Typeface对象Typeface typeFace = Typeface.createFromAsset(getAssets(),"fonts/DroidSansThai.ttf");//
应用字体textView.setTypeface(typeFace);
如果想整个页面都使用同样的字体,可以使用批处理,新增一个Java类,如下:
public class FontManager {  
    
    public static void changeFonts(ViewGroup root, Activity act) {  
    
       Typeface tf = Typeface.createFromAsset(act.getAssets(),  
              "fonts/xxx.ttf");  
    
       for (int i = 0; i < root.getChildCount(); i++) {  
           View v = root.getChildAt(i);  
           if (v instanceof TextView) {  
              ((TextView) v).setTypeface(tf);  
           } else if (v instanceof Button) {  
              ((Button) v).setTypeface(tf);  
           } else if (v instanceof EditText) {  
              ((EditText) v).setTypeface(tf);  
           } else if (v instanceof ViewGroup) {  
              changeFonts((ViewGroup) v, act);  
           }  
       }  
    
    }  
}  

转载请注明 作者:田野光 地址:http://blog.csdn.net/lovefish2/article/details/46129527
在应用开发中,或许你会听到设计狮和产品锦鲤这样抱怨,安卓原生的字体太丑啦,傻大笨粗啊,有没有办法换成细体啊…?不幸的是,安卓字体确实傻大笨粗,其次,只有normal和bold,没有light啊.如果更不幸的是,你看不上安卓可以切换的几种字体,一定要使用自己的字体文件时,该怎么办呢?下面介绍三种方法,让应用换上新的字体.
(注: 前两种方法都有局限性,想要替换整个应用字体的,直接看第三种方法, 对Android Lollipop同样支持)

方法一: 自定义view 
1. 首先, 把你的字体文件放在src/main/assets/fonts 下( /fonts 目录手动新建) 
2. 自定义view继承TextView, 使用自定义view就可以啦
public
class
CustomFontTextView
extends
TextView {
public CustomFontTextView(Context context) {
super(context); init(context); }
public CustomFontTextView(Context context, AttributeSet attrs) {
super(context, attrs); init(context); }
public CustomFontTextView(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr); init(context); }
public
void init(Context context) { Typeface newFont = Typeface.createFromAsset(context.getAssets(),
"fonts/MyFont.ttf"); setTypeface(newFont); }}

方法二: 遍历viewGroup 
我们会发现,第一种方法其实只适用于局部位置修改字体,例如整个布局页面都像要设置自定义字体怎么办呢?我们可以这样做:
public
class
FontHelper {
public
static
final
void setAppFont(ViewGroup mContainer, Typeface mFont,
boolean reflect) {
if (mContainer ==
null || mFont ==
null)
return;
for (int
i = 0; i < mContainer.getChildCount(); ++i) {
final View mChild = mContainer.getChildAt(i);
if (mChild
instanceof TextView) { ((TextView) mChild).setTypeface(mFont); }
else
if (mChild
instanceof EditText) { ((EditText) mChild).setTypeface(mFont);
//你可以在这里添加自定义字体的其他类型的view }
else
if (mChild
instanceof ViewGroup) { setAppFont((ViewGroup) mChild, mFont,
true); }
else
if (reflect) {
try { Method mSetTypeface = mChild.getClass().getMethod("setTypeface",
Typeface.class); mSetTypeface.invoke(mChild, mFont); } catch (Exception e) { e.printStackTrace(); } } } }}
例如我们的布局文件是这样的:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="字体 123 ABC"
android:textColor="@android:color/black"
android:textSize="40dp"/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="字体 123 ABC"
android:textColor="@android:color/black"
android:textSize="40dp"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="字体 123 ABC"
android:textColor="@android:color/black"
android:textSize="40dp"/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="字体 123 ABC"
android:textColor="@android:color/black"
android:textSize="40dp"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="字体 123 ABC"
android:textColor="@android:color/black"
android:textSize="40dp"
android:typeface="sans"/>
</LinearLayout></LinearLayout>

我们可以这样修改字体:
final Typeface mFont = Typeface.createFromAsset(getAssets(),
"fonts/Roboto-Light.ttf");
final ViewGroup mContainer = (ViewGroup) findViewById( android.R.id.content).getRootView();
FontHelper.setAppFont(mContainer, mFont, true);

方法三: 全局映射替换
其实这个方法才是我们绝大多数数时候想要用的, 一次性替换应用全部字体. 
由于官方并没有提供相应的接口,所以这里我们采用的方式时通过反射,获取Typeface类的静态成员变量,并修改对应的字体文件.
这里根据你使用的主题和API的不同,处理方式也有所区别:

非Theme.Material主题
比如你使用的是Theme.Holo主题,或Theme.AppCompat主题, 首先定义一个工具:
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 | IllegalAccessException e) { e.printStackTrace(); } }}

然后在主题里指定使用某种字体(android lollipop设置有区别):
values
<resources>
<style
name="AppBaseTheme"
parent="Theme.AppCompat.Light">
</style>
<!-- Application theme. -->
<style
name="AppTheme"
parent="AppBaseTheme">
<item
name="android:typeface">monospace</item>
</style></resources>

values-v21
<resources>
<style
name="AppTheme"
parent="Theme.AppCompat.Light">
<item
name="android:textAppearance">@style/CustomTextAppearance
</item> </style>
<style
name="CustomTextAppearance">
<item
name="android:typeface">monospace</item>
</style></resources>

最后在你的Application的onCreate()方法里面使用:
FontsOverride.setDefaultFont(this,
"MONOSPACE",
"fonts/MyFont.ttf");

使用Theme.Material主题 
Theme.Material主题是Android 5.0新增的主题
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) {
//android 5.0及以上我们反射修改Typeface.sSystemFontMap变量
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Map<String, Typeface> newMap =
new HashMap<>(); newMap.put(staticTypefaceFieldName, newTypeface);
try {
final Field staticField = Typeface.class .getDeclaredField("sSystemFontMap");
staticField.setAccessible(true); staticField.set(null,
newMap); } catch (NoSuchFieldException | IllegalAccessException e) { e.printStackTrace(); } }
else {
try {
final Field staticField = Typeface.class .getDeclaredField(staticTypefaceFieldName); staticField.setAccessible(true);
staticField.set(null, newTypeface); }
catch (NoSuchFieldException | IllegalAccessException e) { e.printStackTrace(); } } }}

//Material主题默认字体为sans-serif,暂时未找到自定义修改字体的方法FontsOverride.setDefaultFont(this,
"sans-serif",
"fonts/Roboto-Light.ttf");

其他方法: 如使用第三方库Calligraphy,
我没使用过,如果有感兴趣的可以自己尝试一下. 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: