Android修改字體樣式的示例代碼
在Android實(shí)際開(kāi)發(fā)中根據(jù)UI的設(shè)計(jì)圖,經(jīng)常要去改變系統(tǒng)默認(rèn)的字體樣式
這樣做會(huì)使apk變大很多啊
而且為什么android要使用ios的字體-_-#
單獨(dú)設(shè)置字體樣式
(1)Android系統(tǒng)提供了幾種字體樣式可供選擇
通過(guò)設(shè)置typeface屬性或者fontFamily屬性設(shè)置
typeface屬性:
- normal
- serif
- sans
- monospace
fontFamily屬性:
- casual
- cursive
- serif
- monospace
- sans-serif
- sans-serif-condensed
- serif-monospace
- sans-serif-smallcaps

※typeface和fontFamily區(qū)別
android:typeface屬性是增加API1
android:fontFamily在API16(4.1)中添加了屬性
※當(dāng)同時(shí)設(shè)置typeface和fontFamily時(shí),只有fontFamily生效
查看一波TextView的源碼
private void setTypefaceFromAttrs(String familyName, int typefaceIndex, int styleIndex) {
Typeface tf = null;
if (familyName != null) {
tf = Typeface.create(familyName, styleIndex);
if (tf != null) {
setTypeface(tf);
return;
}
}
switch (typefaceIndex) {
case SANS:
tf = Typeface.SANS_SERIF;
break;
case SERIF:
tf = Typeface.SERIF;
break;
case MONOSPACE:
tf = Typeface.MONOSPACE;
break;
}
setTypeface(tf, styleIndex);
}
從方法setTypefaceFromAttrs()看,如果你有set fontFamily屬性,那么typefaceattribute將被忽略。
這邊會(huì)發(fā)現(xiàn)這樣設(shè)置typeface和fontFamily屬性對(duì)中文不生效,這時(shí)候就需要引用外部的字體樣式(這里谷歌設(shè)計(jì)規(guī)范推薦使用NOTO字體https://www.google.com/get/noto/)
(2)使用字體樣式文件設(shè)置(otf,ttf文件都可以)
在assets下新建一個(gè)fonts文件,把字體樣式文件放進(jìn)去

在代碼中設(shè)置
AssetManager mgr = getAssets(); Typeface tf = Typeface.createFromAsset(mgr, "fonts/NotoSansCJKsc-Black.otf"); tv_1.setTypeface(tf);
批量設(shè)置字體樣式
(1)自定義TextView
public class CustomTextView extends TextView
{
public CustomTextView(Context context, AttributeSet attrs)
{
super(context, attrs);
}
//重寫(xiě)設(shè)置字體方法
@Override
public void setTypeface(Typeface tf)
{
tf = Typeface.createFromAsset(getContext().getAssets(), "fonts/NotoSansCJKsc-Light.otf");
super.setTypeface(tf);
}
}
之后在XML布局文件中使用CustomTextView代替TextView
<com.test.fontfamily.CustomTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="6dp"
android:text="自定義字體"
android:textSize="24dp"
/>

(2)更換整個(gè)App的字體
思路:遍歷找到所有的TextView然后替換字體
百度了一下找到下面工具類
package com.test.fontfamily;
import android.app.Application;
import android.content.Context;
import android.graphics.Typeface;
import android.support.annotation.NonNull;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.lang.ref.SoftReference;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
/**
* Created by Administrator on 2017/10/24.
*/
public class FontUtils
{
private static final String TAG = FontUtils.class.getSimpleName();
private Map<String, SoftReference<Typeface>> mCache = new HashMap<>();
private static FontUtils sSingleton = null;
public static Typeface DEFAULT = Typeface.DEFAULT;
// disable instantiate
private FontUtils()
{
}
public static FontUtils getInstance()
{
// double check
if (sSingleton == null)
{
synchronized (FontUtils.class)
{
if (sSingleton == null)
{
sSingleton = new FontUtils();
}
}
}
return sSingleton;
}
/**
* <p>Replace the font of specified view and it's children</p>
*
* @param root The root view.
* @param fontPath font file path relative to 'assets' directory.
*/
public void replaceFontFromAsset(@NonNull View root, @NonNull String fontPath)
{
replaceFont(root, createTypefaceFromAsset(root.getContext(), fontPath));
}
/**
* <p>Replace the font of specified view and it's children</p>
*
* @param root The root view.
* @param fontPath font file path relative to 'assets' directory.
* @param style One of {@link Typeface#NORMAL}, {@link Typeface#BOLD}, {@link Typeface#ITALIC}, {@link Typeface#BOLD_ITALIC}
*/
public void replaceFontFromAsset(@NonNull View root, @NonNull String fontPath, int style)
{
replaceFont(root, createTypefaceFromAsset(root.getContext(), fontPath), style);
}
/**
* <p>Replace the font of specified view and it's children</p>
*
* @param root The root view.
* @param fontPath The full path to the font data.
*/
public void replaceFontFromFile(@NonNull View root, @NonNull String fontPath)
{
replaceFont(root, createTypefaceFromFile(fontPath));
}
/**
* <p>Replace the font of specified view and it's children</p>
*
* @param root The root view.
* @param fontPath The full path to the font data.
* @param style One of {@link Typeface#NORMAL}, {@link Typeface#BOLD}, {@link Typeface#ITALIC}, {@link Typeface#BOLD_ITALIC}
*/
public void replaceFontFromFile(@NonNull View root, @NonNull String fontPath, int style)
{
replaceFont(root, createTypefaceFromFile(fontPath), style);
}
/**
* <p>Replace the font of specified view and it's children with specified typeface</p>
*/
private void replaceFont(@NonNull View root, @NonNull Typeface typeface)
{
if (root == null || typeface == null)
{
return;
}
if (root instanceof TextView)
{ // If view is TextView or it's subclass, replace it's font
TextView textView = (TextView) root;
// Extract previous style of TextView
int style = Typeface.NORMAL;
if (textView.getTypeface() != null)
{
style = textView.getTypeface().getStyle();
}
textView.setTypeface(typeface, style);
} else if (root instanceof ViewGroup)
{ // If view is ViewGroup, apply this method on it's child views
ViewGroup viewGroup = (ViewGroup) root;
for (int i = 0; i < viewGroup.getChildCount(); ++i)
{
replaceFont(viewGroup.getChildAt(i), typeface);
}
} // else return
}
/**
* <p>Replace the font of specified view and it's children with specified typeface and text style</p>
*
* @param style One of {@link Typeface#NORMAL}, {@link Typeface#BOLD}, {@link Typeface#ITALIC}, {@link Typeface#BOLD_ITALIC}
*/
private void replaceFont(@NonNull View root, @NonNull Typeface typeface, int style)
{
if (root == null || typeface == null)
{
return;
}
if (style < 0 || style > 3)
{
style = Typeface.NORMAL;
}
if (root instanceof TextView)
{ // If view is TextView or it's subclass, replace it's font
TextView textView = (TextView) root;
textView.setTypeface(typeface, style);
} else if (root instanceof ViewGroup)
{ // If view is ViewGroup, apply this method on it's child views
ViewGroup viewGroup = (ViewGroup) root;
for (int i = 0; i < viewGroup.getChildCount(); ++i)
{
replaceFont(viewGroup.getChildAt(i), typeface, style);
}
} // else return
}
/**
* <p>Create a Typeface instance with specified font file</p>
*
* @param fontPath font file path relative to 'assets' directory.
* @return Return created typeface instance.
*/
private Typeface createTypefaceFromAsset(Context context, String fontPath)
{
SoftReference<Typeface> typefaceRef = mCache.get(fontPath);
Typeface typeface = null;
if (typefaceRef == null || (typeface = typefaceRef.get()) == null)
{
typeface = Typeface.createFromAsset(context.getAssets(), fontPath);
typefaceRef = new SoftReference<>(typeface);
mCache.put(fontPath, typefaceRef);
}
return typeface;
}
private Typeface createTypefaceFromFile(String fontPath)
{
SoftReference<Typeface> typefaceRef = mCache.get(fontPath);
Typeface typeface = null;
if (typefaceRef == null || (typeface = typefaceRef.get()) == null)
{
typeface = Typeface.createFromFile(fontPath);
typefaceRef = new SoftReference<>(typeface);
mCache.put(fontPath, typefaceRef);
}
return typeface;
}
/**
* <p>Replace system default font. <b>Note:</b>you should also add code below to your app theme in styles.xml. </p>
* {@code <item name="android:typeface">monospace</item>}
* <p>The best place to call this method is {@link Application#onCreate()}, it will affect
* whole app font.If you call this method after view is visible, you need to invalid the view to make it effective.</p>
*
* @param context {@link Context Context}
* @param fontPath font file path relative to 'assets' directory.
*/
public void replaceSystemDefaultFontFromAsset(@NonNull Context context, @NonNull String fontPath)
{
replaceSystemDefaultFont(createTypefaceFromAsset(context, fontPath));
}
/**
* <p>Replace system default font. <b>Note:</b>you should also add code below to your app theme in styles.xml. </p>
* {@code <item name="android:typeface">monospace</item>}
* <p>The best place to call this method is {@link Application#onCreate()}, it will affect
* whole app font.If you call this method after view is visible, you need to invalid the view to make it effective.</p>
*
* @param context {@link Context Context}
* @param fontPath The full path to the font data.
*/
public void replaceSystemDefaultFontFromFile(@NonNull Context context, @NonNull String fontPath)
{
replaceSystemDefaultFont(createTypefaceFromFile(fontPath));
}
/**
* <p>Replace system default font. <b>Note:</b>you should also add code below to your app theme in styles.xml. </p>
* {@code <item name="android:typeface">monospace</item>}
* <p>The best place to call this method is {@link Application#onCreate()}, it will affect
* whole app font.If you call this method after view is visible, you need to invalid the view to make it effective.</p>
*/
private void replaceSystemDefaultFont(@NonNull Typeface typeface)
{
modifyObjectField(null, "MONOSPACE", typeface);
}
private void modifyObjectField(Object obj, String fieldName, Object value)
{
try
{
Field defaultField = Typeface.class.getDeclaredField(fieldName);
defaultField.setAccessible(true);
defaultField.set(obj, value);
} catch (NoSuchFieldException e)
{
e.printStackTrace();
} catch (IllegalAccessException e)
{
e.printStackTrace();
}
}
}
閱讀源碼發(fā)現(xiàn)這里面主要方法有
replaceFont()
替換一個(gè)頁(yè)面中的所有字體。用遞歸的方式去查找view是否是TextView或者TextView的子類,然后進(jìn)行替換。不過(guò)這種方法效率不高
用法:在頁(yè)面中
FontUtils.getInstance().replaceFontFromAsset(View root, String fontPath)
modifyObjectField()
替換App所有字體。利用反射替換系統(tǒng)默認(rèn)字體
用法:
a.新建一個(gè)BaseApplication繼承Application在onCreate方法中
FontUtils.getInstance().replaceSystemDefaultFontFromAsset(this,"fonts/NotoSansCJKsc-Thin.otf");
b.在AppTheme中添加
<item name="android:typeface">monospace</item>
c.清單文件中使用BaseApplication
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android webView字體突然變小的原因及解決
- Android使用TypeFace設(shè)置TextView的文字字體
- Android開(kāi)發(fā)TextvView實(shí)現(xiàn)鏤空字體效果示例代碼
- 淺析Android加載字體包及封裝的方法
- Android開(kāi)發(fā)之FloatingActionButton懸浮按鈕基本使用、字體、顏色用法示例
- 詳解android 中文字體向上偏移解決方案
- Android如何動(dòng)態(tài)調(diào)整應(yīng)用字體大小詳解
- Android Studio設(shè)置、改變字體和主題的方法
- android 更改TextView中任意位置字體大小和顏色的方法
- Android字體相關(guān)知識(shí)總結(jié)
相關(guān)文章
Android編程中Activity的四種啟動(dòng)模式
這篇文章主要介紹了Android編程中Activity的四種啟動(dòng)模式,較為詳細(xì)的分析了Activity四種啟動(dòng)模式的原理與功能,需要的朋友可以參考下2016-04-04
Android RecyclerView自由拖動(dòng)item的實(shí)現(xiàn)代碼
這篇文章主要介紹了Android RecyclerView自由拖動(dòng)item的實(shí)現(xiàn)代碼,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2024-01-01
Android簡(jiǎn)易圖片瀏覽器的實(shí)現(xiàn)
最近做了一個(gè)圖片瀏覽小程序,本文主要介紹了Android簡(jiǎn)易圖片瀏覽器的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-03-03
Android獲取assets文件夾中的數(shù)據(jù)并寫(xiě)入SD卡示例
這篇文章主要介紹了Android獲取assets文件夾中的數(shù)據(jù)并寫(xiě)入SD卡示例,對(duì)初學(xué)Android開(kāi)發(fā)的朋友來(lái)說(shuō)是一個(gè)很實(shí)用的功能,需要的朋友可以參考下2014-07-07
完美解決android M上鎖屏情況下,禁止pc通過(guò)MTP訪問(wèn)手機(jī)存儲(chǔ)單元
下面小編就為大家?guī)?lái)一篇完美解決android M上鎖屏情況下,禁止pc通過(guò)MTP訪問(wèn)手機(jī)存儲(chǔ)單元。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-04-04
Android自定義View模仿即刻點(diǎn)贊數(shù)字切換效果實(shí)例
有一個(gè)項(xiàng)目是仿即刻的點(diǎn)贊,這篇文章主要給大家介紹了關(guān)于Android自定義View模仿即刻點(diǎn)贊數(shù)字切換效果的相關(guān)資料,文中通過(guò)示例代碼介紹 的非常詳細(xì),需要的朋友可以參考下2022-12-12
android截圖事件監(jiān)聽(tīng)的原理與實(shí)現(xiàn)
本篇文章主要介紹了android截圖事件監(jiān)聽(tīng)的原理與實(shí)現(xiàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-07-07
淺扒Android動(dòng)態(tài)設(shè)置字體大小的示例
本篇文章主要介紹了淺扒Android動(dòng)態(tài)設(shè)置字體大小的示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-12-12
Android向Excel寫(xiě)入數(shù)據(jù)導(dǎo)出U盤(pán)并發(fā)送郵件
這篇文章主要為大家詳細(xì)介紹了Android將數(shù)據(jù)寫(xiě)入Excel格式導(dǎo)出U盤(pán)、發(fā)送郵件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07

