【最新版本已支援selector,通過程式碼生成drawable,詳情檢視 github.com/JavaNoober/…
關於如何進行預覽,檢視文章
無需自定義View,徹底解放shape,selector(二)
如果有什麼問題,方便大家交流,建立了一個qq群,群號887686934,歡迎大家加入
前言
作為一個android程式設計師,對於shape、selector這兩個標籤一定不陌生。每當UI設計師給我們設計出一個個button背景的時候,我們就需要去drawable資料夾下去新建一個bg_xxx.xml,然後很多時候區別僅僅是一個邊框的顏色或者填充的顏色。這就導致了很多非常相似的.xml檔案產生。
網上之前也有了一種通過自定義View,在xml中通過設定屬性達到shape效果的控制元件。但是這種自定義的控制元件不太靈活,歸根到底是一個自定義的button,如果我想改造專案的話就得去替換原有的button或者textView。接下來就給大家提供一種更加簡單的方式:
無需自定義View,直接新增屬性便可以實現shape、selector效果。
具體內容
效果展示
話不多說,直接上程式碼。
使用方法:
1、在BaseActiviy的super.onCreate()之前呼叫一行程式碼,僅僅是一個方法
佈局程式碼
我們來新增一些例項屬性:
有沒有覺得很熟悉,就是原生標籤的tag名+_+屬性名,很容易記住,而且不管是Button還是TextView,只要是View都可以。效果
我們來看一下實際效果:
通過配置Live Templates,實現自動程式碼提示修改背景
現在UI設計師告訴我們要改一下背景,沒事,我們只需要在xml新增或者修改屬性就行。
我們來把圓形改成正方形,加個邊框。5秒ok!
簡單的原理解析
app:xxx
app:xxx屬性就不用多說了,這些就是一些自定義屬性而已。在這裡我把shape、selector的部分屬性轉換成自定義的屬性,這樣就方便新增到已有原生控制元件中。
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 常用換膚方式以及原理分析
具體使用方法:
新增依賴:
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"//設定水波紋顏色
複製程式碼
注意:
1、如果直接給原生控制元件新增屬性,在xml中會如下報紅色異常,這時候不用理會即可。
tools:ignore="MissingPrefix"
複製程式碼
即可
2、如果Button設定背景的時候文字顯示不全,需要設定padding為0,這是button的系統預設風格導致的。3、當前為了快速使用selector只支援press事件,後續會把所有selector事件加上。
4、Fragment因為依附在Activity上,所以無需特殊處理即可使用
結尾
專案地址:github.com/JavaNoober/…
後續更新完善內容會在專案裡標明,大家的star是我繼續研究的動力☺!
如果有什麼問題,方便大家交流,建立了一個qq群,群號887686934,歡迎大家加入