玩转安卓字体
起因
最近公司有個需求,需要做 Widget ,內心其實是拒絕的,因為這個玩意兒特別難用,而且限制重重,但沒辦法,也不能不做,那就開始吧。
本來以為挺簡單的東西,一個列表展示數據,然后再展示一些基本數據,兩天搞定,然后拿給 UI 去看,下面是和UI的對話。
UI:你照著藍湖做了嘛?
我:有啥問題嗎?(很納悶。。。我就是照著藍湖做的啊!)
UI:你看你這個時間的字體和我圖上的不一樣啊!
我:額。。。行吧,我回去想想辦法,你把字體發給我吧(內心一萬只草泥馬走過。。。)
原生字體
很久沒搞過字體了,安卓系統一共為我們預制了四種字體,來看下吧:
來看個例子吧:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center_horizontal"android:orientation="vertical"tools:context=".MainActivity"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_margin="10dp"android:text="Normal"android:textColor="#000"android:textSize="30sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_margin="10dp"android:fontFamily="sans-serif"android:text="Sans"android:textColor="#000"android:textSize="30sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_margin="10dp"android:fontFamily="serif"android:text="Serif"android:textColor="#000"android:textSize="30sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_margin="10dp"android:fontFamily="monospace"android:text="Monospace"android:textColor="#000"android:textSize="30sp" /></LinearLayout>上面例子很簡單,一個線性布局包裹著上面描述的系統預制的四種字體,來看下效果圖吧:
其實并不是只能像上面這樣來進行使用,上面的四種還可以進行相互組合,也可以有不同的效果,大家可以自己試試:
字體并不是只能在布局文件中進行修改,在代碼中同樣可以進行修改:
//設置字體樣式 mainText.typeface = Typeface.SANS_SERIF mainText.typeface = Typeface.SERIF如果沒有什么特殊要求的話,上面的這幾種字體基本就能滿足大部分的開發需求了,而且還都可以對字體進行加粗和斜體,就更能滿足了。
使用三方字體
但UI并不認為安卓預制的幾種字體好看,就想弄點不一樣的字體😂,那也沒辦法,就來看看怎么設置吧。
引入字體
既然想使用三方字體,那第一步肯定是要引入下三方字體文件,字體文件后綴為 .ttf,需要將字體文件放到assets->fonts文件夾中,項目中沒有這個文件夾不要緊,自己新建一個即可。
使用
使用很簡單,通過AssetsManager就能獲取到字體文件,然后直接通過setTypeFace方法將字體設置下即可:
//從asset 讀取字體 根據路徑得到Typeface val tf = Typeface.createFromAsset(assets, "fonts/你的字體名稱.ttf") //設置字體 mainText.typeface = tf問題
至此為止,上面的內容就是百度安卓字體能出來的內容,但是!!!沒法用啊,文章開頭就說到了,我現在做的是 AppWidget 啊,限制非常多,只能通過 RemoteView 的一些固定方法來設置控件的值,但 RemoteView 中并沒有可以設置字體的方法,這該咋辦呢???
百度了半天也沒有找到結果,就想著能不能在 Application 中通過反射將 TextView 的字體中其中一個的默認字體給修改成我想要的字體,然后通過設置主題的方法給 AppWidget 中的 TextView 進行設置以來達到修改字體的結果。
先來寫下 Application 中的字體替換代碼:
class App : Application() {override fun onCreate() {super.onCreate()updateFont()}private fun updateFont() {val regular = Typeface.createFromAsset(assets,"fonts/你的字體名稱.ttf")replaceFont(regular)}@SuppressLint("DiscouragedPrivateApi")private fun replaceFont(newTypeface: Typeface) {val newMap: MutableMap<String?, Typeface> = HashMap()newMap["MONOSPACE"] = newTypefacetry {val staticField = Typeface::class.java.getDeclaredField("sSystemFontMap")staticField.isAccessible = truestaticField[null] = newMap} catch (e: Exception) {e.printStackTrace()}}}下面來在主題中設置下:
<!-- 字體 theme. --> <style name="FontAppTheme" parent="Theme.AppCompat"><item name="android:typeface">monospace</item> </style>之后就可以在 TextView 中進行設置了:
<TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_margin="10dp"android:text="12:34"android:textColor="#000"android:textSize="30sp"android:theme="@style/FontAppTheme" />解決方案
上面的這種方法太麻煩,而且還使用了反射,太不友好了。就想著去看看官方文檔吧,沒準有什么好用的方法呢。
果然。。。。進入官方文檔的第一句話就給我整笑了。。。
What?只需要像放圖片一樣在 res 中建一個 font 文件夾,然后將字體放進去,就可以像使用圖片一樣來使用字體了???
那我搞上面一堆干啥??
嗯。。。。遇到問題還是盡量少百度,多看官方文檔吧。。
而且動態設置字體的時候也沒必要像之前那樣通過 AssetsManager 來獲取字體了,只需要通過 Resources 就可以獲取到了:
val tf = resources.getFont(R.font.myfont) mainText.typeface = tf這是字體官方文檔的地址:https://developer.android.google.cn/guide/topics/ui/look-and-feel/fonts-in-xml
總結
哎,其實很簡單的一個東西,而且在 Android 8.0 的時候就已經實現的東西,現在馬上都 Android 12 了我竟然都不知道,慚愧啊!!!
好了,就這樣吧,大家以后遇到問題還是多看文檔吧。。。千萬不要學我。
總結
- 上一篇: 5大关键,让你二十年后依然是人才
- 下一篇: lodop直接打印服务器的文件,C-Lo