話說,怎麼纔算實戰?在此以前我已經使用Kotlin
寫過幾個項目了,從最初的一邊看文檔一邊面向QQ羣編程,到如今本身也能夠和衆人侃侃而談Kotlin
的基礎語法,那麼問題來了——我爲何如今纔開始叫「Kotlin
實戰」呢?由於我以前敲代碼都是規規矩矩沒有任何問題,可是最近在使用一個項目的時候,遇到了很多問題,所以作一個總結,但願能夠幫到其餘人。html
先給你們簡單介紹一下項目的來源:重構UIWidget的RadiusView
.爲何要重構呢?由於在使用過程當中以爲這個模塊的功能很強大,可是在使用的過程當中有一些默認屬性不是很熟悉,甚至以爲是bug,因而打算熟悉此此項目並重構並放到本身的項目模板中。可是我在重構過程當中遇到一些困難:java
我對泛型的瞭解,僅限於Java
中的泛型方法、泛型類,以爲沒有什麼難度,因而看見代碼直接幹。先看看java
代碼是什麼樣的?android
public class RadiusViewDelegate<T extends RadiusViewDelegate> {
...
}
複製代碼
soSeay,這個類的聲明確實很簡單,因而我三下五除二的很快寫好了,代碼以下:git
咦?咋不行呢?沒事,我還有一招,java
轉Kotlin
代碼,巴拉巴拉魔法變:github
咋這招也不靈呢?不是說好java
能夠作的事情,Kotlin
也能夠作的嗎?原來童話都是騙人的?編程
open class RadiusViewDelegate<T : RadiusViewDelegate<T>>(
val a: View,
open val b: Context,
open val c: AttributeSet?
)
open class B<T : RadiusViewDelegate<T>>(a: View, b: Context, c: AttributeSet?) :RadiusViewDelegate<T >(a,b,c){
}
複製代碼
看來童話確實是存在的,Java
能夠乾的活Kotlin
照樣能幹!可是還有一個問題,如何聲明B
這個對象呢?直接寫確定是不行的,不信的話你能夠試一下,固然,我也能夠給你截一張圖:api
那麼咱們應該怎麼解決呢?不是說好童話是存在的嗎?咱們嘗試一下聲明C
繼承B
而後使用C
這個對象,代碼以下:bash
class C(a: View, b: Context, c: AttributeSet?):B<C>(a, b, c){
}
val b = C(radiusSwitch,this,null)
複製代碼
看來這樣是能夠的,那麼咱們爲何要經過繼承來實現呢?或者,咱們爲何要使用這樣的泛型呢?回答了第二個問題,第一個問題都不是問題了。此處使用泛型的緣由是爲了使子類能夠鏈式調用父類的方法。衆所周知,爲了鏈式調用,咱們能夠對調用的方法增長一個返回值this
,這樣就能夠實現鏈式調用了。可是涉及子類繼承呢?子類調用父類的方法返回的是父類,雖然能夠強轉也不會報錯,可是這樣強轉之後的「鏈式調用」還算鏈式調用嗎?話說回來,咱們怎麼經過增長一個泛型實現鏈式調用呢? 咱們在頂層父類增長一個返回this
的方法,而後包括子類全部須要返回this
的地方都調用這個方法便可。app
open class RadiusViewDelegate<T : RadiusViewDelegate<T>>(
val a: View,
open val b: Context,
open val c: AttributeSet?
){
fun back(): T {
return this as T
}
}
複製代碼
到這裏咱們就解決了爲何使用泛型、怎麼使用泛型,可是咱們尚未認真去了解一下什麼是泛型?知其然,知其因此然才能更好的瞭解童話是否是騙人的,所以咱們去看看官方文檔:jvm
Java 類型系統中最棘手的部分之一是通配符類型(參見 Java Generics FAQ)。 而 Kotlin 中沒有。 相反,它有兩個其餘的東西:聲明處型變(declaration-site variance)與類型投影(type projections)。
看完之後,第一個感受就是咱們此處的泛型屬於聲明處型變,而且咱們的泛型約束還能夠換一種寫法,所以修改一下代碼:
open class RadiusViewDelegate<out T> @JvmOverloads constructor(
val view: View,
val context: Context,
val attrs: AttributeSet? = null
) where T : RadiusViewDelegate<T> {
fun back(): T {
return this as T
}
}
複製代碼
這裏的鏈式調用有童鞋建議說可使用構造者模式和接口來實現,優勢是在back
方法中能夠避免這種強行轉換的方式,可是這種寫法基本上咱們的RadiusViewDelegate
及其子類都須要一個單獨的接口,我認爲代碼可讀性有降低,所以沒有繼續糾結,有興趣的朋友能夠嘗試一下。
在Kotlin
當中,一個類容許被繼承只須要在class
前添加一個關鍵字open
,使用的時候用:
替換java
中的extends
便可。一句話的事情,我爲何會單獨拿出來講事呢?由於在使用過程當中我遇到了兩個坑。
我寫了一個類
RadiusTextDelegate
繼承自上文中的RadiusViewDelegate
,在使用的時候發現一個很是奇葩的問題:其父類RadiusViewDelegate
的代碼報錯,可是單獨使用其父類RadiusViewDelegate
的時候一切正常。報錯代碼以下:
val mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.RadiusView)
//日誌
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.TypedArray android.content.Context.obtainStyledAttributes(android.util.AttributeSet, int[])' on a null object reference
at com.vincent.baselibrary.widget.radius.delegate.RadiusViewDelegate.<init>(RadiusViewDelegate.kt:96)
複製代碼
添加斷點檢查的時候,父類和子類的參數都同樣,貌似均不爲空。
就是這個斷點,讓我誤覺得context
和attrs
均不爲空,後來通過請教朱凱大佬才明白attrs
已經爲空了! 咱們再來看看這個源碼:
open class RadiusViewDelegate<out T> @JvmOverloads constructor(
val view: View,
open val context: Context,
open val attrs: AttributeSet? = null
) where T : RadiusViewDelegate<T> {
init {
val mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.RadiusView)
initAttributes(mTypedArray)
...
}
...
}
open class RadiusTextDelegate<T> constructor(
private val textView: TextView,
override val context: Context,
override val attrs: AttributeSet?
) :
RadiusViewDelegate<T>(textView, context, attrs) where T : RadiusViewDelegate<T> {
}
複製代碼
看了一下源碼更加不明白,爲何context
和attrs
傳給父類後就空了呢?經過面向QQ羣編程發現無效,後來嘗試將Kotlin
代碼轉化爲Java
代碼後發現了問題:
package com.vincent.baseproject.ui;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TextView;
import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@Metadata(
mv = {1, 1, 15},
bv = {1, 0, 3},
k = 1,
d1 = {"\u0000 \n\u0002\u0018\u0002\n\u0000\n\u0002\u0018\u0002\n\u0000\n\u0002\u0018\u0002\n\u0000\n\u0002\u0018\u0002\n\u0000\n\u0002\u0018\u0002\n\u0002\b\u0006\b\u0016\u0018\u0000*\u000e\b\u0000\u0010\u0001*\b\u0012\u0004\u0012\u0002H\u00010\u00022\b\u0012\u0004\u0012\u0002H\u00010\u0002B\u001f\u0012\u0006\u0010\u0003\u001a\u00020\u0004\u0012\u0006\u0010\u0005\u001a\u00020\u0006\u0012\b\u0010\u0007\u001a\u0004\u0018\u00010\b¢\u0006\u0002\u0010\tR\u0016\u0010\u0007\u001a\u0004\u0018\u00010\bX\u0096\u0004¢\u0006\b\n\u0000\u001a\u0004\b\n\u0010\u000bR\u0014\u0010\u0005\u001a\u00020\u0006X\u0096\u0004¢\u0006\b\n\u0000\u001a\u0004\b\f\u0010\rR\u000e\u0010\u0003\u001a\u00020\u0004X\u0082\u0004¢\u0006\u0002\n\u0000¨\u0006\u000e"},
d2 = {"Lcom/vincent/baseproject/ui/RadiusTextDelegate;", "T", "Lcom/vincent/baseproject/ui/RadiusViewDelegate;", "textView", "Landroid/widget/TextView;", "context", "Landroid/content/Context;", "attrs", "Landroid/util/AttributeSet;", "(Landroid/widget/TextView;Landroid/content/Context;Landroid/util/AttributeSet;)V", "getAttrs", "()Landroid/util/AttributeSet;", "getContext", "()Landroid/content/Context;", "app_debug"}
)
public class RadiusTextDelegate extends RadiusViewDelegate {
private final TextView textView;
@NotNull
private final Context context;
@Nullable
private final AttributeSet attrs;
@NotNull
public Context getContext() {
return this.context;
}
@Nullable
public AttributeSet getAttrs() {
return this.attrs;
}
public RadiusTextDelegate(@NotNull TextView textView, @NotNull Context context, @Nullable AttributeSet attrs) {
Intrinsics.checkParameterIsNotNull(textView, "textView");
Intrinsics.checkParameterIsNotNull(context, "context");
super((View)textView, context, attrs);
this.textView = textView;
this.context = context;
this.attrs = attrs;
}
}
// RadiusViewDelegate.java
package com.vincent.baseproject.ui;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import com.vincent.baseproject.R.styleable;
import kotlin.Metadata;
import kotlin.jvm.JvmOverloads;
import kotlin.jvm.internal.DefaultConstructorMarker;
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@Metadata(
mv = {1, 1, 15},
bv = {1, 0, 3},
k = 1,
d1 = {"\u0000,\n\u0002\u0018\u0002\n\u0000\n\u0002\u0010\u0000\n\u0000\n\u0002\u0018\u0002\n\u0000\n\u0002\u0018\u0002\n\u0000\n\u0002\u0018\u0002\n\u0002\b\b\n\u0002\u0010\u0002\n\u0000\n\u0002\u0018\u0002\n\u0000\b\u0016\u0018\u0000*\u0010\b\u0000\u0010\u0001 \u0001*\b\u0012\u0004\u0012\u0002H\u00010\u00002\u00020\u0002B#\b\u0007\u0012\u0006\u0010\u0003\u001a\u00020\u0004\u0012\u0006\u0010\u0005\u001a\u00020\u0006\u0012\n\b\u0002\u0010\u0007\u001a\u0004\u0018\u00010\b¢\u0006\u0002\u0010\tJ\u0012\u0010\u0010\u001a\u00020\u00112\b\u0010\u0012\u001a\u0004\u0018\u00010\u0013H\u0002R\u0016\u0010\u0007\u001a\u0004\u0018\u00010\bX\u0096\u0004¢\u0006\b\n\u0000\u001a\u0004\b\n\u0010\u000bR\u0014\u0010\u0005\u001a\u00020\u0006X\u0096\u0004¢\u0006\b\n\u0000\u001a\u0004\b\f\u0010\rR\u0011\u0010\u0003\u001a\u00020\u0004¢\u0006\b\n\u0000\u001a\u0004\b\u000e\u0010\u000f¨\u0006\u0014"},
d2 = {"Lcom/vincent/baseproject/ui/RadiusViewDelegate;", "T", "", "view", "Landroid/view/View;", "context", "Landroid/content/Context;", "attrs", "Landroid/util/AttributeSet;", "(Landroid/view/View;Landroid/content/Context;Landroid/util/AttributeSet;)V", "getAttrs", "()Landroid/util/AttributeSet;", "getContext", "()Landroid/content/Context;", "getView", "()Landroid/view/View;", "initAttributes", "", "typedArray", "Landroid/content/res/TypedArray;", "app_debug"}
)
public class RadiusViewDelegate {
@NotNull
private final View view;
@NotNull
private final Context context;
@Nullable
private final AttributeSet attrs;
private final void initAttributes(TypedArray typedArray) {
}
@NotNull
public final View getView() {
return this.view;
}
@NotNull
public Context getContext() {
return this.context;
}
@Nullable
public AttributeSet getAttrs() {
return this.attrs;
}
@JvmOverloads
public RadiusViewDelegate(@NotNull View view, @NotNull Context context, @Nullable AttributeSet attrs) {
Intrinsics.checkParameterIsNotNull(view, "view");
Intrinsics.checkParameterIsNotNull(context, "context");
super();
this.view = view;
this.context = context;
this.attrs = attrs;
TypedArray typedArray = this.getContext().obtainStyledAttributes(this.getAttrs(), styleable.RadiusView);
this.initAttributes(typedArray);
}
// $FF: synthetic method
public RadiusViewDelegate(View var1, Context var2, AttributeSet var3, int var4, DefaultConstructorMarker var5) {
if ((var4 & 4) != 0) {
var3 = (AttributeSet)null;
}
this(var1, var2, var3);
}
@JvmOverloads
public RadiusViewDelegate(@NotNull View view, @NotNull Context context) {
this(view, context, (AttributeSet)null, 4, (DefaultConstructorMarker)null);
}
}
複製代碼
仔細查看RadiusViewDelegate
的構造方法RadiusViewDelegate(@NotNull View view, @NotNull Context context, @Nullable AttributeSet attrs)
方法下第七行代碼得知,context
和attrs
並非使用構造方法的參數,而是經過get
方法獲取的,而問題就出在get
方法。由於RadiusTextDelegate
的構造方法參數context
使用了兩個關鍵字override val
,因此將該文件轉成Java
代碼後子類生成了以下方法:
@NotNull
public Context getContext() {
return this.context;
}
複製代碼
話說回來,父類經過getContext()
方法獲取Context
時,子類尚未來得及將參數賦值給成員變量this.context
,所以就產生了異常'android.content.res.TypedArray android.content.Context.obtainStyledAttributes(android.util.AttributeSet, int[])' on a null object reference
。 解決方案很簡單,將子類的構造方法參數修改一下便可:
open class RadiusViewDelegate<out T> @JvmOverloads constructor(
val view: View,
val context: Context,
val attrs: AttributeSet? = null
) where T : RadiusViewDelegate<T> {
}
open class RadiusTextDelegate<T> constructor(
private val textView: TextView,
context: Context,
attrs: AttributeSet?
) :
RadiusViewDelegate<T>(textView, context, attrs) where T : RadiusViewDelegate<T> {
}
複製代碼
經過上面的例子能夠簡單的說一下構造方法參數關鍵字的用法,val
和var
就不解釋了,open
表明子類會重寫父類的get
方法和set
方法(若是是var
類型參數),而子類若是使用和父類徹底一致的參數名稱,則不能不添加override
關鍵字。添加override
關鍵字之後,若是父類的參數是var
則子類也不能修改成val
類型,反之,子類構造方法參數的類型則不受限制了。
通常咱們在自定義View
的時候,常見構造方法有以下兩種有隱患的寫法,以下:
/// 第一種
class CountdownView: TextView{
constructor(context: Context) : this(context,null)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs,0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
}
/// 第二種
class CountdownView @JvmOverloads constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : TextView(context, attrs, defStyleAttr) {
}
複製代碼
我在自定義RadiusSwitch
的時候使用了第二種構造方法,結果遇到了一堆異常。
java.lang.NullPointerException: Attempt to invoke interface method 'int java.lang.CharSequence.length()' on a null object reference
at android.widget.Switch.makeLayout(Switch.java:896)
at android.widget.Switch.onMeasure(Switch.java:815)
複製代碼
網上百度、谷歌找到如下幾種解決方案:
theme
設置錯誤——未發現錯誤Context
設置錯誤——斷點檢查是當前Activity
textOff
和textOn
屬性——添加之後Switch
的樣式顯示有問題,可是能解決閃退。經過和原生的Switch
添加斷點對比之後發現是mShowText
未被設置爲true
,可是經過xml
文件配置屬性可解決。接下來又發現Switch
的點擊事件無效了。最後查看源碼發現是clickable
也被設置爲false
,致使點擊事件無效。固然,也能夠經過xml
配置屬性解決。 可是始終是沒有找到問題的根源,最後再次檢查源碼發現原來是構造方法使用錯誤,由於我調用的是Switch(Context context, AttributeSet attrs, int defStyleAttr)
,而xml
佈局文件中的控件是使用的構造方法應該是Switch(Context context, AttributeSet attrs)
,而兩者的構造方法區別在於下面:
public Switch(Context context, AttributeSet attrs) {
this(context, attrs, com.android.internal.R.attr.switchStyle);
}
public Switch(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
複製代碼
找到錯誤的根本緣由之後,解決就很簡單了:固然再也不是xml
配置上面提到的這些默認屬性了,而是修改構造方法,以下:
class RadiusSwitch : Switch {
var delegate: RadiusSwitchDelegateImp? = null
constructor(context: Context) : super(context) {
delegate = RadiusSwitchDelegateImp(this, context, null)
}
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs,0) {
delegate = RadiusSwitchDelegateImp(this, context, attrs)
}
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int = 0) : super(context, attrs, defStyleAttr) {
delegate = RadiusSwitchDelegateImp(this, context, attrs)
}
}
複製代碼
到此實戰填坑就結束了,接下來仍是給你們看看這個模塊的效果圖,而後告訴你們怎麼使用。
<!--View默認樣式-->
<!-- 圓角矩形背景色 -->
<attr name="rv_backgroundColor" format="color"/>
<!-- 圓角矩形背景色Pressed -->
<attr name="rv_backgroundPressedColor" format="color"/>
<!-- 圓角矩形背景色Disabled -->
<attr name="rv_backgroundDisabledColor" format="color"/>
<!-- 圓角矩形背景色Selected -->
<attr name="rv_backgroundSelectedColor" format="color"/>
<!-- 圓角矩形背景色Checked -->
<attr name="rv_backgroundCheckedColor" format="color"/>
<!-- 圓角矩形背景色按下狀態透明度(0-255默認0 僅當未設置backgroundPressedColor有效) -->
<attr name="rv_backgroundPressedAlpha" format="integer"/>
<!-- 圓角邊框顏色-->
<attr name="rv_strokeColor" format="color"/>
<!-- 圓角邊框顏色Pressed -->
<attr name="rv_strokePressedColor" format="color"/>
<!-- 圓角邊框顏色Disabled -->
<attr name="rv_strokeDisabledColor" format="color"/>
<!-- 圓角邊框顏色Selected -->
<attr name="rv_strokeSelectedColor" format="color"/>
<!-- 圓角邊框顏色Checked -->
<attr name="rv_strokeCheckedColor" format="color"/>
<!-- 圓角矩形邊框色按下狀態透明度(0-255默認0 僅當未設置strokePressedColor有效) -->
<attr name="rv_strokePressedAlpha" format="integer"/>
<!-- 圓角線框,單位dp-->
<attr name="rv_strokeWidth" format="dimension"/>
<!-- 圓角線框虛線的寬度,單位dp-->
<attr name="rv_strokeDashWidth" format="dimension"/>
<!-- 圓角線框虛線的間隙,單位dp-->
<attr name="rv_strokeDashGap" format="dimension"/>
<!-- 圓角弧度是高度一半-->
<attr name="rv_radiusHalfHeightEnable" format="boolean"/>
<!-- 圓角矩形寬高相等,取較寬高中大值-->
<attr name="rv_widthHeightEqualEnable" format="boolean"/>
<!-- 圓角弧度,單位dp-->
<attr name="rv_radius" format="dimension"/>
<!-- 圓角弧度,單位dp,TopLeft-->
<attr name="rv_topLeftRadius" format="dimension"/>
<!-- 圓角弧度,單位dp,TopRight-->
<attr name="rv_topRightRadius" format="dimension"/>
<!-- 圓角弧度,單位dp,BottomLeft-->
<attr name="rv_bottomLeftRadius" format="dimension"/>
<!-- 圓角弧度,單位dp,BottomRight-->
<attr name="rv_bottomRightRadius" format="dimension"/>
<!-- 水波紋顏色-->
<attr name="rv_rippleColor" format="color"/>
<!-- 是否有Ripple效果,api21+有效-->
<attr name="rv_rippleEnable" format="boolean"/>
<!--View選中狀態-->
<attr name="rv_selected" format="boolean"/>
<!--View背景狀態進入狀態延時(非水波紋)-->
<attr name="rv_enterFadeDuration" format="integer"/>
<!--View背景狀態退出狀態延時(非水波紋)-->
<attr name="rv_exitFadeDuration" format="integer"/>
<!-- 文字顏色-->
<attr name="rv_textColor" format="color"/>
<!-- 文字顏色Pressed-->
<attr name="rv_textPressedColor" format="color"/>
<!-- 文字顏色Disabled-->
<attr name="rv_textDisabledColor" format="color"/>
<!-- 文字顏色Selected-->
<attr name="rv_textSelectedColor" format="color"/>
<!-- 文字顏色Checked-->
<attr name="rv_textCheckedColor" format="color"/>
<!--設置EditText在調用setText後默認光標置於末尾-->
<attr name="rv_selectionEndEnable" format="boolean"/>
<!--設置EditText在調用setText後默認光標置於末尾只執行一次-->
<attr name="rv_selectionEndOnceEnable" format="boolean"/>
<!--如下爲TextView Drawable Left Top Right Bottom 寬高及各類狀態屬性-->
<!--是否系統自帶drawableLeft樣式-->
<attr name="rv_leftDrawableSystemEnable" format="boolean"/>
<!--設置drawable爲顏色值(ColorDrawable)時的圓角弧度-->
<attr name="rv_leftDrawableColorRadius" format="dimension"/>
<!--設置drawable爲顏色值(ColorDrawable)時是否圓形-->
<attr name="rv_leftDrawableColorCircleEnable" format="boolean"/>
<!--drawable寬高屬性當drawable爲顏色值(ColorDrawable)時必須設置不然顯示不出-->
<attr name="rv_leftDrawableWidth" format="dimension"/>
<attr name="rv_leftDrawableHeight" format="dimension"/>
<attr name="rv_leftDrawable" format="reference|color"/>
<attr name="rv_leftPressedDrawable" format="reference|color"/>
<attr name="rv_leftDisabledDrawable" format="reference|color"/>
<attr name="rv_leftSelectedDrawable" format="reference|color"/>
<attr name="rv_leftCheckedDrawable" format="reference|color"/>
<!--drawable寬高屬性當drawable爲顏色值(ColorDrawable)時必須設置不然顯示不出-->
<!--是否系統自帶drawableTop樣式-->
<attr name="rv_topDrawableSystemEnable" format="boolean"/>
<!--設置drawable爲顏色值(ColorDrawable)時的圓角弧度-->
<attr name="rv_topDrawableColorRadius" format="dimension"/>
<!--設置drawable爲顏色值(ColorDrawable)時是否圓形-->
<attr name="rv_topDrawableColorCircleEnable" format="boolean"/>
<!--drawable寬高屬性當drawable爲顏色值(ColorDrawable)時必須設置不然顯示不出-->
<attr name="rv_topDrawableWidth" format="dimension"/>
<attr name="rv_topDrawableHeight" format="dimension"/>
<attr name="rv_topDrawable" format="reference|color"/>
<attr name="rv_topPressedDrawable" format="reference|color"/>
<attr name="rv_topDisabledDrawable" format="reference|color"/>
<attr name="rv_topSelectedDrawable" format="reference|color"/>
<attr name="rv_topCheckedDrawable" format="reference|color"/>
<!--drawable寬高屬性當drawable爲顏色值(ColorDrawable)時必須設置不然顯示不出-->
<!--是否系統自帶drawableRight樣式-->
<attr name="rv_rightDrawableSystemEnable" format="boolean"/>
<!--設置drawable爲顏色值(ColorDrawable)時的圓角弧度-->
<attr name="rv_rightDrawableColorRadius" format="dimension"/>
<!--設置drawable爲顏色值(ColorDrawable)時是否圓形-->
<attr name="rv_rightDrawableColorCircleEnable" format="boolean"/>
<!--drawable寬高屬性當drawable爲顏色值(ColorDrawable)時必須設置不然顯示不出-->
<attr name="rv_rightDrawableWidth" format="dimension"/>
<attr name="rv_rightDrawableHeight" format="dimension"/>
<attr name="rv_rightDrawable" format="reference|color"/>
<attr name="rv_rightPressedDrawable" format="reference|color"/>
<attr name="rv_rightDisabledDrawable" format="reference|color"/>
<attr name="rv_rightSelectedDrawable" format="reference|color"/>
<attr name="rv_rightCheckedDrawable" format="reference|color"/>
<!--drawable寬高屬性當drawable爲顏色值(ColorDrawable)時必須設置不然顯示不出-->
<!--是否系統自帶drawableBottom樣式-->
<attr name="rv_bottomDrawableSystemEnable" format="boolean"/>
<!--設置drawable爲顏色值(ColorDrawable)時的圓角弧度-->
<attr name="rv_bottomDrawableColorRadius" format="dimension"/>
<!--設置drawable爲顏色值(ColorDrawable)時是否圓形-->
<attr name="rv_bottomDrawableColorCircleEnable" format="boolean"/>
<!--drawable寬高屬性當drawable爲顏色值(ColorDrawable)時必須設置不然顯示不出-->
<attr name="rv_bottomDrawableWidth" format="dimension"/>
<attr name="rv_bottomDrawableHeight" format="dimension"/>
<attr name="rv_bottomDrawable" format="reference|color"/>
<attr name="rv_bottomPressedDrawable" format="reference|color"/>
<attr name="rv_bottomDisabledDrawable" format="reference|color"/>
<attr name="rv_bottomSelectedDrawable" format="reference|color"/>
<attr name="rv_bottomCheckedDrawable" format="reference|color"/>
<!--以上爲TextView Drawable Left Top Right Bottom 寬高及各類狀態屬性-->
<!--如下爲CompoundButton ButtonDrawable 寬高及不一樣狀態屬性-->
<!--drawable寬高屬性當drawable爲顏色值(ColorDrawable)時方有效-->
<!--是否系統自帶Button樣式-->
<attr name="rv_buttonDrawableSystemEnable" format="boolean"/>
<!--設置drawable爲顏色值(ColorDrawable)時的圓角弧度-->
<attr name="rv_buttonDrawableColorRadius" format="dimension"/>
<!--設置drawable爲顏色值(ColorDrawable)時是否圓形-->
<attr name="rv_buttonDrawableColorCircleEnable" format="boolean"/>
<attr name="rv_buttonDrawableWidth" format="dimension"/>
<attr name="rv_buttonDrawableHeight" format="dimension"/>
<attr name="rv_buttonDrawable" format="reference|color"/>
<attr name="rv_buttonPressedDrawable" format="reference|color"/>
<attr name="rv_buttonDisabledDrawable" format="reference|color"/>
<attr name="rv_buttonSelectedDrawable" format="reference|color"/>
<attr name="rv_buttonCheckedDrawable" format="reference|color"/>
複製代碼
以上屬性也能夠經過代碼來設置,以下:
rtv_javaBg.delegate?.run {
this.setTextCheckedColor(Color.BLUE)
.setBackgroundCheckedColor(Color.WHITE)
.setRadius(resources.getDimension(R.dimen.dp_radius))
.setStrokeWidth(resources.getDimensionPixelSize(R.dimen.dp_stroke_width))
.setStrokeColor(ContextCompat.getColor(this@RadiusActivity,android.R.color.holo_purple))
.setStrokeDashWidth(resources.getDimension(R.dimen.dp_dash_width))
.setStrokeDashGap(resources.getDimension(R.dimen.dp_dash_gap))
.initShape()
}
複製代碼
以上爲我的理解,水平有限,還請各位斧正!