無需自定義View,完全解放shape,selector吧

【最新版本已支持selector,經過代碼生成drawable,詳情查看 github.com/JavaNoober/…
關於如何進行預覽,查看文章 無需自定義View,完全解放shape,selector(二)android

若是有什麼問題,方便你們交流,建立了一個qq羣,羣號887686934,歡迎你們加入git

前言

做爲一個android程序員,對於shape、selector這兩個標籤必定不陌生。每當UI設計師給咱們設計出一個個button背景的時候,咱們就須要去drawable文件夾下去新建一個bg_xxx.xml,而後不少時候區別僅僅是一個邊框的顏色或者填充的顏色。這就致使了不少很是類似的.xml文件產生。
網上以前也有了一種經過自定義View,在xml中經過設置屬性達到shape效果的控件。可是這種自定義的控件不太靈活,歸根究竟是一個自定義的button,若是我想改造項目的話就得去替換原有的button或者textView。接下來就給你們提供一種更加簡單的方式:
無需自定義View,直接添加屬性即可以實現shape、selector效果程序員

具體內容

效果展現

話很少說,直接上代碼。
從1.5.0版本開始,無需任何代碼,直接加入標籤便可,請使用最新版本
使用方法:
一、在BaseActiviy的super.onCreate()以前調用一行代碼,僅僅是一個方法github

二、沒有其餘操做了,直接layout裏開始寫控件吧!

佈局代碼

咱們來添加一些實例屬性:app

有沒有以爲很熟悉,就是 原生標籤的tag名+_+屬性名,很容易記住,並且不論是Button仍是TextView, 只要是View均可以。

效果

咱們來看一下實際效果:框架

經過配置Live Templates,實現自動代碼提示

修改背景

如今UI設計師告訴咱們要改一下背景,沒事,咱們只須要在xml添加或者修改屬性就行。
咱們來把圓形改爲正方形,加個邊框。5秒ok!佈局

簡單的原理解析

app:xxx

app:xxx屬性就不用多說了,這些就是一些自定義屬性而已。在這裏我把shape、selector的部分屬性轉換成自定義的屬性,這樣就方便添加到已有原生控件中。post

BackgroundLibrary.inject(this)

這個方法是這個框架惟一須要加入的代碼。
inject中其實是給LayoutInflater添加了一個LayoutInflater.Factory類。而Android的Activity在建立過程(也就是setContentView)中其實是經過把xml轉換成View的對象。而LayoutInflater.Factory至關於這中間的一個後門,它是xml解析建立成View的必經方法,google中的v7support包裏不少內容就是經過LayoutInflater.Factory來實現向下兼容的。
在這裏,我經過低入侵的方式,加入一個自定義的LayoutInflater.Factory,去解析添加的自定義屬性,接下來就簡單了。生成系統提供的GradientDrawable、RippleDrawable、StateListDrawable便可。
同時因爲AppcompatActivity是已經實現了LayoutInflater.Factory,而Activity又設定一個Activity只能加入一個factory類,所以這裏須要在super.onCreate以前調用該方法,利用AppcompatActivity的factory去建立View。
具體原理解釋能夠參考個人這篇文章:Android 經常使用換膚方式以及原理分析this

具體使用方法:

添加依賴:google

implementation "com.android.support:appcompat-v7:$supportVersion"
implementation 'com.noober.backgorund:core:1.0.5'
複製代碼

BaseActivity的super.onCreate以前添加代碼:

BackgroundLibrary.inject(context);
複製代碼

支持屬性,命名規則就是標籤名_標籤屬性名,支持shape全部屬性:

<attr name="shape" format="enum">
       <enum name="rectangle" value="0" />
       <enum name="oval" value="1" />
       <enum name="line" value="2" />
       <enum name="ring" value="3" />
   </attr>

   <attr name="solid_color" format="color"/>

   <attr name="corners_radius" format="dimension"/>
   <attr name="corners_bottomLeftRadius" format="dimension"/>
   <attr name="corners_bottomRightRadius" format="dimension"/>
   <attr name="corners_topLeftRadius" format="dimension"/>
   <attr name="corners_topRightRadius" format="dimension"/>

   <attr name="gradient_angle" format="integer"/>
   <attr name="gradient_centerX" format="float"/>
   <attr name="gradient_centerY" format="float"/>
   <attr name="gradient_centerColor" format="color"/>
   <attr name="gradient_endColor" format="color"/>
   <attr name="gradient_startColor" format="color"/>
   <attr name="gradient_gradientRadius" format="dimension"/>
   <attr name="gradient_type" format="enum">
       <enum name="linear" value="0" />
       <enum name="radial" value="1" />
       <enum name="sweep" value="2" />
   </attr>
   <attr name="gradient_useLevel" format="boolean"/>

   <attr name="padding_left" format="dimension"/>
   <attr name="padding_top" format="dimension"/>
   <attr name="padding_right" format="dimension"/>
   <attr name="padding_bottom" format="dimension"/>

   <attr name="size_width" format="dimension">
       <enum name="wrap_content" value="-2" />
       <enum name="match_parent" value="-1" />
   </attr>
   <attr name="size_height" format="dimension">
       <enum name="wrap_content" value="-2" />
       <enum name="match_parent" value="-1" />
   </attr>

   <attr name="stroke_width" format="dimension"/>
   <attr name="stroke_color" format="color"/>
   <attr name="stroke_dashWidth" format="dimension"/>
   <attr name="stroke_dashGap" format="dimension"/>

   <!--如下是selector事件-->
   <attr name="ripple_enable" format="boolean"/>
   <attr name="ripple_color" format="color"/>
   <attr name="unpressed_color" format="color"/>
   <attr name="pressed_color" format="color"/>
複製代碼

例如加一個邊框背景,以下便可:

<TextView
    android:layout_width="130dp"
    android:layout_height="36dp"
    android:gravity="center"
    android:text="TextView"
    android:textColor="#8c6822"
    android:textSize="20sp"
    app:corners_radius="4dp"
    app:solid_color="#E3B666"
    app:stroke_color="#8c6822"
    app:stroke_width="2dp" />
複製代碼

若是須要selector效果,須要同時添加

app:unpressed_color
app:pressed_color
複製代碼

若是須要水波紋效果,5.0以上才支持:

app:ripple_enable="true"//打開水波紋開關
app:solid_color="xxx"//設置默認填充顏色
app:ripple_color="xxx"//設置水波紋顏色
複製代碼

注意:
一、若是直接給原生控件添加屬性,在xml中會以下報紅色異常,這時候不用理會便可。

可是紅色多了,顯示總歸難受,能夠在根節點添加

tools:ignore="MissingPrefix" 
複製代碼

便可

二、若是Button設置背景的時候文字顯示不全,須要設置padding爲0,這是button的系統默認風格致使的。
三、當前爲了快速使用selector只支持press事件,後續會把全部selector事件加上。
四、Fragment由於依附在Activity上,因此無需特殊處理便可使用

結尾

項目地址:github.com/JavaNoober/…
後續更新完善內容會在項目裏標明,你們的star是我繼續研究的動力☺!
若是有什麼問題,方便你們交流,建立了一個qq羣,羣號887686934,歡迎你們加入

相關文章
相關標籤/搜索