使用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

 

 本文由用戶 ouyangbbbbwwww 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!