使用DataBinding來進行字體的自定義
寫在前面
在Android應用開發中,由于客戶或者個人的需要(誰叫Android默認的字體那么丑 ),所以需要配置不同的字體,而 Android 只能在 xml 中配置系統默認提供的四種字體,需要自定義的字體都需要在 Java 代碼中配置。
總結一下以前自定義字體的方法
1 .通過findViewById找到view,然后一個個的去設置字體
Typeface customFont = Typeface.createFromAsset(this.getAssets(), "fonts/customFont.ttf"); TextView view = (TextView) findViewById(R.id.text); view.setTypeface(customFont);
? 一個看著還好,可是應用中可是有很多的文本或者按鈕的,不可能逐個去設置。于是大多數都選擇了第二種方法。
2 .創建一個子類,繼承自TextView或者Button等等
public class CustomTextView extends TextView { public CustomTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public CustomTextView(Context context, AttributeSet attrs) { super(context, attrs); } public CustomTextView(Context context) { super(context); } public void setTypeface(Typeface tf, int style) { if (style == Typeface.BOLD) { super.setTypeface(Typeface.createFromAsset(getContext().getAssets(), "fonts/CustomFont_Bold.ttf")); } else { super.setTypeface(Typeface.createFromAsset(getContext().getAssets(), "fonts/CustomFont.ttf")); } } }
然后在xml文件中每次都使用自定義的View,相比上一個方案,這一個要稍微好點。但相信都達不到各位的要求,只不過是換一個字體,需要這么麻煩嗎?
3 . Calligraphy
這是一個開源庫,地址是 https://github.com/chrisjenx/Calligraphy ,在github上5000+star,感覺還是不錯的,也從側面說出自定義字體的需求量有多大。
那么接下來就講重點了
如何使用DataBinding來進行字體的自定義呢?
TOO EASY,不用每次都去手寫,也不需要自定義View
首先,打開DataBinding
android { compileSdkVersion 25 buildToolsVersion "25.0.0" defaultConfig { } buildTypes { } dataBinding { enabled = true } }
再看結構
在項目中的assets/fonts文件夾下加入了5種字體,然后在 strings.xml 中定義了字體的路徑
而在layout的xml中只需要這么使用,那么便已經完成了8成了
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center"> <TextView android:layout_width="match_parent" android:layout_height="50dp" android:gravity="center" android:text="Hello world" android:textSize="18sp" android:typeface="@{@string/nutso2}"/> <TextView android:layout_width="match_parent" android:layout_height="50dp" android:gravity="center" android:textSize="18sp" android:text="Hello world" android:typeface="@{@string/notoSans_regular}"/> <TextView android:layout_width="match_parent" android:layout_height="50dp" android:gravity="center" android:textSize="18sp" android:text="Hello world" android:typeface="@{@string/notoSansui_boldItalic}"/> <TextView android:layout_width="match_parent" android:layout_height="50dp" android:gravity="center" android:text="Hello world" android:textSize="18sp" android:typeface="@{@string/icomoon}"/> <TextView android:layout_width="match_parent" android:layout_height="50dp" android:gravity="center" android:text="Hello world" android:textSize="18sp" android:typeface="@{@string/ruthie}"/> </LinearLayout> </layout>
而剩下的兩成,一成在 FontBinding 文件
public class FontBinding { @BindingConversion public static Typeface convertStringToFace(String s){ try { return Typeface.createFromAsset(FontApp.getInstance().getAssets(),s); }catch (Exception e){ throw e; } } }
這里定義了一個轉換器,將xml文件中獲取到的字符資源,轉換成了一個 Typeface
最后一成,只需要使用就好了
public class MainActivity extends AppCompatActivity { ActivityMainBinding mMainBinding; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main); } }
看一下截圖,一起哈啤
沒了解過DataBinding的人可能不知道 ActivityMainBinding 是怎么來的,這是編譯時生成的,在如下圖所示的位置可以找到 打開 ActivityMainBinding 可以看到這樣的代碼
this.mboundView1.setTypeface(com.ditclear.sample.FontBinding.convertStringToFace(mboundView1.getResources().getString(R.string.nutso2))); this.mboundView2.setTypeface(com.ditclear.sample.FontBinding.convertStringToFace(mboundView2.getResources().getString(R.string.notoSans_regular))); this.mboundView3.setTypeface(com.ditclear.sample.FontBinding.convertStringToFace(mboundView3.getResources().getString(R.string.notoSansui_boldItalic))); this.mboundView4.setTypeface(com.ditclear.sample.FontBinding.convertStringToFace(mboundView4.getResources().getString(R.string.icomoon))); this.mboundView5.setTypeface(com.ditclear.sample.FontBinding.convertStringToFace(mboundView5.getResources().getString(R.string.ruthie)));
這些 mboundViewX 就是xml中的TextView,由于沒寫id,所以都是自動生成的名稱,可以看到給每一個使用了綁定的TextView都設置了字體,相當于系統幫我們做了第一個方法中重復性的工作。
當然我們還可以優化一下,由于每次都要操作assests文件夾,也會帶來一定的開銷,所以也有必要提供一個字體緩存 FontCache
public class FontCache { private static ArrayMap<String, Typeface> fontCache = new ArrayMap<String, Typeface>(); public static Typeface getTypeface(String fontName, Context context) { Typeface tf = fontCache.get(fontName); if(tf == null) { try { tf = Typeface.createFromAsset(context.getAssets(), fontName); } catch (Exception e) { return null; } fontCache.put(fontName, tf); } return tf; } }
那么 FontBinding 就變成了這樣
public class FontBinding { @BindingConversion public static Typeface convertStringToFace(String fontName){ try { return FontCache.getTypeface(fontName,FontApp.getInstance()); }catch (Exception e){ throw e; } } }
補充: 如果不想每次都在xml中設置字體,可以在綁定一個常用的屬性時設置一個默認的字體。比如字體是需要作用在 text 上的,那么我們只需要在 setText 的時候綁定一個默認的字體就?了,看代碼
public class FontBinding { @BindingAdapter("android:text") public static void setText(TextView v, String s){ v.setTypeface(convertStringToFace(FontApp.getInstance().getString(R.string.ruthie))); v.setText(s); } }
這樣在綁定文本的時候就會綁定一個默認的字體,不用每次都寫
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center"> <TextView android:layout_width="match_parent" android:layout_height="50dp" android:gravity="center" android:text="@{@string/hello_world}" android:textSize="18sp"/> <TextView android:layout_width="match_parent" android:layout_height="50dp" android:gravity="center" android:textSize="18sp" android:text="@{@string/hello_world}" android:typeface="@{@string/notoSans_regular}"/> </LinearLayout> </layout>
最后,效果圖:
好了,大功告成!這也算是一種新思路吧。
來自:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2017/0118/7054.html