Android修改字體樣式的示例代碼
在Android實際開發(fā)中根據(jù)UI的設計圖,經(jīng)常要去改變系統(tǒng)默認的字體樣式
這樣做會使apk變大很多啊
而且為什么android要使用ios的字體-_-#
單獨設置字體樣式
(1)Android系統(tǒng)提供了幾種字體樣式可供選擇
通過設置typeface屬性或者fontFamily屬性設置
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)中添加了屬性
※當同時設置typeface和fontFamily時,只有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將被忽略。
這邊會發(fā)現(xiàn)這樣設置typeface和fontFamily屬性對中文不生效,這時候就需要引用外部的字體樣式(這里谷歌設計規(guī)范推薦使用NOTO字體https://www.google.com/get/noto/)
(2)使用字體樣式文件設置(otf,ttf文件都可以)
在assets下新建一個fonts文件,把字體樣式文件放進去

在代碼中設置
AssetManager mgr = getAssets(); Typeface tf = Typeface.createFromAsset(mgr, "fonts/NotoSansCJKsc-Black.otf"); tv_1.setTypeface(tf);
批量設置字體樣式
(1)自定義TextView
public class CustomTextView extends TextView
{
public CustomTextView(Context context, AttributeSet attrs)
{
super(context, attrs);
}
//重寫設置字體方法
@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)更換整個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()
替換一個頁面中的所有字體。用遞歸的方式去查找view是否是TextView或者TextView的子類,然后進行替換。不過這種方法效率不高
用法:在頁面中
FontUtils.getInstance().replaceFontFromAsset(View root, String fontPath)
modifyObjectField()
替換App所有字體。利用反射替換系統(tǒng)默認字體
用法:
a.新建一個BaseApplication繼承Application在onCreate方法中
FontUtils.getInstance().replaceSystemDefaultFontFromAsset(this,"fonts/NotoSansCJKsc-Thin.otf");
b.在AppTheme中添加
<item name="android:typeface">monospace</item>
c.清單文件中使用BaseApplication
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
- Android webView字體突然變小的原因及解決
- Android使用TypeFace設置TextView的文字字體
- Android開發(fā)TextvView實現(xiàn)鏤空字體效果示例代碼
- 淺析Android加載字體包及封裝的方法
- Android開發(fā)之FloatingActionButton懸浮按鈕基本使用、字體、顏色用法示例
- 詳解android 中文字體向上偏移解決方案
- Android如何動態(tài)調(diào)整應用字體大小詳解
- Android Studio設置、改變字體和主題的方法
- android 更改TextView中任意位置字體大小和顏色的方法
- Android字體相關知識總結
相關文章
Android RecyclerView自由拖動item的實現(xiàn)代碼
這篇文章主要介紹了Android RecyclerView自由拖動item的實現(xiàn)代碼,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧2024-01-01
Android獲取assets文件夾中的數(shù)據(jù)并寫入SD卡示例
這篇文章主要介紹了Android獲取assets文件夾中的數(shù)據(jù)并寫入SD卡示例,對初學Android開發(fā)的朋友來說是一個很實用的功能,需要的朋友可以參考下2014-07-07
完美解決android M上鎖屏情況下,禁止pc通過MTP訪問手機存儲單元
下面小編就為大家?guī)硪黄昝澜鉀Qandroid M上鎖屏情況下,禁止pc通過MTP訪問手機存儲單元。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-04-04
Android自定義View模仿即刻點贊數(shù)字切換效果實例
有一個項目是仿即刻的點贊,這篇文章主要給大家介紹了關于Android自定義View模仿即刻點贊數(shù)字切換效果的相關資料,文中通過示例代碼介紹 的非常詳細,需要的朋友可以參考下2022-12-12
android截圖事件監(jiān)聽的原理與實現(xiàn)
本篇文章主要介紹了android截圖事件監(jiān)聽的原理與實現(xiàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-07-07
Android向Excel寫入數(shù)據(jù)導出U盤并發(fā)送郵件
這篇文章主要為大家詳細介紹了Android將數(shù)據(jù)寫入Excel格式導出U盤、發(fā)送郵件,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-07-07

