话说,怎么才算实战?在此以前我已经使用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()
}
复制代码
以上为我的理解,水平有限,还请各位斧正!