無需自定義View,徹底解放shape,selector(二)

JavaNoober發表於2019-02-15

無需自定義View,徹底解放shape,selector(二)

前言

新年快樂,大家好,我又來了。。。
這篇文章主要是介紹我之前的一個框架BackgroundLibrary預覽功能的實現
相信很多人看過我之前的文章: 無需自定義View,徹底解放shape,selector吧 , 通過自定義標籤去設定shape、selector的屬性,省去了一大部分的shape.xml檔案。
專案釋出5個月,也累計了1500+的star,現在也基本穩定執行在各個專案中了。

無需自定義View,徹底解放shape,selector(二)

問題

但是美中不足的是,雖然BackgroundLibrary這個庫解決了繁瑣的xml問題,確始終無法解決預覽問題(下圖所示),開發者只能直接在app中看到效果,無法在as中看到效果。這讓我們開發的時候造成了一定的不便。

無需自定義View,徹底解放shape,selector(二)

BackgroundLibrary原理是通過給原生控制元件新增自定義屬性,然後在執行時期生成drawable,這樣產生了shape、selector。而as是不會去編譯程式碼的,這就導致了,在沒有編譯的時候編譯器無法進行預覽。

如何實現預覽

Anko

首先我想到了一個同樣類似原理的框架Anko,通過動態生成佈局來提高app效能,它實現預覽的方式是通過實現一個自定義預覽外掛,然後需要預覽的時候,每次build一下專案,然後進行預覽,顯然這種方式和我們直接執行app沒有太大的區別,而且開發外掛的成本較高,不適合採用這種方法。

Android Studio編譯器

那麼as是如何實現view的預覽的呢?
我們簡單看一下TextView的原始碼:

無需自定義View,徹底解放shape,selector(二)
TextView有三個建構函式,通常我們在通過程式碼生成佈局的時候只會用到new TextView(context)這樣的方式去生成物件,而且TextView還有兩個建構函式,多了一個引數AttributeSet,而這個引數所包涵的便是我們在layout.xml中對View設定的各種屬性,as編譯器通過呼叫這個建構函式,實現了View的預覽。
而這種方法對於這個框架來說是可行的,因此為了方便大家可以預覽,我同樣實現了對應的自定義View。

效果及使用方法

效果

無需自定義View,徹底解放shape,selector(二)

使用方法

1、如果需要對View進行預覽,直接把原來的View換成框架內對應的BLView即可,即可展示預覽效果,如果不需要預覽可以直接忽略這些用於預覽的自定義View;
2、如果沒有效果,make project一下即可;
3、如果BLView中沒有對應的需要預覽的View,可以很簡單的自己實現一下,以BLTextView為例:

public class BLTextView extends AppCompatTextView {
    public BLTextView(Context context) {
        super(context);
    }

    public BLTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    public BLTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs){
        BackgroundFactory.setViewBackground(context, attrs, this);
    }
}
複製程式碼

繼承所需要預覽的View,然後在建構函式中新增BackgroundFactory.setViewBackground(context, attrs, this)方法即可。
注意
為了提高效能,這些View在編譯的時候會自動替換為對應原生的View,所以除了再xml中,不要在程式碼中出現任何的BLTextView,否則會報類似如下的錯誤:

//錯誤
BLTextView button = findViewById(R.id.text);
//正確
BLTextView button = findViewById(R.id.text);


Caused by: java.lang.ClassCastException: android.support.v7.widget.AppCompatTextView cannot be cast to com.noober.background.view.BLTextView
複製程式碼

總結

上面就是我實現思路的一個方式,只需一行程式碼setViewBackground去實現自定義View,來進行預覽,並且在執行時替換自定義View,這樣在開發的時候除了需要預覽的情況,我們完全可以忽略這些自定義控制元件的存在,這對android sdk的升級改變都不會產生任何影響。歡迎大家提供更多的思路。

相關文章