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

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

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 > < 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 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 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, 我没使用过,如果有感兴趣的可以自己尝试一下. 


你可能感兴趣的:(android)