自己的事情自己来,手写一个自定义Drawable控件

533 阅读8分钟

一,背景

随着项目的逐步增大,业务逐步的迭代累加,我们的代码当中除了日益增加的业务代码外,一些资源文件例如图片,layout,drawable文件也是越来越多,它们虽然占不了apk多大的体积,但是对于后期维护,尤其是做过资源整理,无用资源删除,或者需要兼容多种主题色样式需求的同学来讲,那简直是一件费体力,脑力,精力的事情,没错,我们可以借助一些工具比如Android Studio里面的lint工具去检索这些文件,但虽然可以把无用资源检索出来,但以防万一,还是得逐个看看每个文件是否真的是无用的

article_1.jpg

大部分图片我们可以用矢量图去代替,布局文件我们也可以把公共布局抽取出来用include,merge标签来引用,比较头疼的是drawable文件,时常会因为一些细小的元素,诸如背景色,渐变色,圆角大小,边框颜色,点击后的反馈颜色的不同,会生成不同的文件,多人开发中如果规范没有定好,这些文件的命名也是五花八门,造成后面视觉如果要更换ui图,稍微更改一下一些元素,我们又得很无奈的重新在新建一个drawable文件,导致后期drawable文件下的文件越来越多难以维护,就像这个样子

article_2.jpg

实际情况可能还要多,那有没有办法解决drawable文件频繁创建的问题呢,没错,就是自定义一个布局控件,将这些元素都集中在这个控件的属性中去,我们要用的时候,也就是把这些色值,圆角大小等赋给这些属性就好,后期就算视觉要改设计图,对于我们来讲,动几个属性的事情,一个字,倍儿爽~

article_3.jpg

二,调研

其实这类控件市面上已经有不少开发者开源了自己的代码,比如ShadowLayout,大家可以在自己的项目配置文件中去远程依赖使用,但我个人还是比较喜欢手写一个,一个原因是不太喜欢去依赖这种控件类第三方插件,还有一个就是项目各异,还是根据实际情况去写控件,方便因需求设计变更可以随时做更改,先罗列下这个控件需要支持那些属性

属性名称作用需要支持的格式类型
joy_bg_color背景颜色reference
joy_start_color渐变色起始颜色reference
joy_end_color渐变色结束颜色reference
joy_direction渐变方向string
joy_corner_radius圆角大小reference dimension
joy_lt_corner_radius左上圆角大小reference dimension
joy_lb_corner_radius左下圆角大小reference dimension
joy_rt_corner_radius右上圆角大小reference dimension
joy_rb_corner_radius右下圆角大小reference dimension
joy_stroke_width线框大小reference dimension
joy_stroke_color线框颜色reference
joy_shape_style形状样式string
joy_pressed_bg_color点击下去的背景颜色reference
joy_pressed_start_color点击下去的渐变色起始颜色reference
joy_pressed_end_color点击下去的渐变色结束颜色reference
joy_pressed_direction点击下去的渐变方向string
joy_ripple点击是否需要水波纹效果boolean
joy_ripple_color水波纹色值boolean

其中像背景色,渐变,圆角等,我们需要用到GradientDrawable,而点击反馈的状态,我们需要用到StateListDrawable,而水波纹效果,就需要RippleDrawable,它们都是Drawable的子类,Drawable还有其他别的子类,这里没用到就不介绍了

三,自定义控件JoySelectorLayout编写

3.1 先声明需要用到的Drawable对象

/**
 * 渲染背景,普通正常状态下的样式
 */
private lateinit var normalDrawables: GradientDrawable

/**
 * 渲染背景,点击状态下的样式
 */
private lateinit var pressedDrawables: GradientDrawable

/**
 * 状态背景,设置普通,点击状态的样式
 */
private lateinit var stateDrawable: StateListDrawable

/**
 * 水波纹背景
 */
private lateinit var rippleDrawable: RippleDrawable

3.2 创建背景颜色

背景颜色分纯色与渐变色,优先判断有没有设置纯色(joy_bg_color),如果有直接纯色背景,如果没有设置则看有没有设置渐变起始色(joy_start_color)与渐变终止色(joy_end_color),渐变起始色与渐变终止色默认颜色都为透明

/**
 * 创建背景颜色
 */
private fun createColors(typedArray: TypedArray): IntArray {
    var bgColor = typedArray.getColor(
        R.styleable.JoySelectorLayout_joy_bg_color, -1
    )
    val colors = if (bgColor != -1) {
        intArrayOf(bgColor, bgColor)
    } else {
        intArrayOf(
            typedArray.getColor(
                R.styleable.JoySelectorLayout_joy_start_color,
                0
            ),
            typedArray.getColor(
                R.styleable.JoySelectorLayout_joy_end_color,
                0
            )
        )
    }
    return colors
}

3.3 确定渐变方向

GradientDrawable有三种渐变方向,线性渐变(LINEAR_GRADIENT),放射性渐变(RADIAL_GRADIENT),扇形渐变(SWEEP_GRADIENT),默认线性渐变,这边也主要以线性渐变为例。创建一个GradientDrawable需要两个参数,一个是颜色,这个我们已经定义好了,另一个是渐变方向,我们通过属性joy_direction来决定用什么方向,GradientDrawable总共有八种方向,分别是从左往右(LEFT_RIGHT),从上往下(TOP_BOTTOM),从右往左(RIGHT_LEFT),从下往上(BOTTOM_TOP),从左上到右下(TL_BR),从左下到右上(BL_TR),从右上到左下(TR_BL),从右下到左上(BR_TL),所以joy_direction声明了八个value一一对应

<attr name="joy_direction" format="string">
    <enum name="start_to_end" value="1"/>
    <enum name="top_to_bottom" value="2"/>
    <enum name="end_to_start" value="3"/>
    <enum name="bottom_to_top" value="4"/>
    <enum name="starttop_to_endbottom" value="5"/>
    <enum name="endtop_to_startbottom" value="6"/>
    <enum name="startbottom_to_endtop" value="7"/>
    <enum name="endbottom_to_starttop" value="8"/>
</attr>

代码当中默认使用从左往右方向,其余根据输入自行匹配

/**
 * 决定用哪个方向的GradientDrawable
 */
private fun createGradientDrawable(
    typedArray: TypedArray
): GradientDrawable {
    val direction = typedArray.getString(
        R.styleable.JoySelectorLayout_joy_direction
    )
    val colors = createColors(typedArray)
    
    return GradientDrawable(
        when (direction) {
            "2" -> GradientDrawable.Orientation.TOP_BOTTOM
            "3" -> GradientDrawable.Orientation.RIGHT_LEFT
            "4" -> GradientDrawable.Orientation.BOTTOM_TOP
            "5" -> GradientDrawable.Orientation.TL_BR
            "6" -> GradientDrawable.Orientation.TR_BL
            "7" -> GradientDrawable.Orientation.BL_TR
            "8" -> GradientDrawable.Orientation.BR_TL
            else -> GradientDrawable.Orientation.LEFT_RIGHT
        }, colors
    )
}

3.4 创建圆角

圆角也是先去判断joy_corner_radius有没有值,有的话则表示所有圆角都是这个大小,否则去判断joy_lt_corner_radius,joy_lb_corner_radius,joy_rt_corner_radius,joy_rb_corner_radius有没有值,有则表示某一个角的圆角已被设置

/**
 * 创建圆角
 */
private fun createRadius(typedArray: TypedArray): FloatArray {
    val radius =
        typedArray.getDimension(R.styleable.JoySelectorLayout_joy_corner_radius, 0f)
    return if (radius != 0f)
        floatArrayOf(radius, radius, radius, radius, radius, radius, radius, radius)
    else
        createCornerArray(typedArray)
}
/**
 * 创建圆弧半径数组
 */
private fun createCornerArray(typedArray: TypedArray): FloatArray {
    return floatArrayOf(
        typedArray.getDimension(
            R.styleable.JoySelectorLayout_joy_lt_corner_radius,
            0f
        ),
        typedArray.getDimension(
            R.styleable.JoySelectorLayout_joy_lt_corner_radius,
            0f
        ),
        typedArray.getDimension(
            R.styleable.JoySelectorLayout_joy_rt_corner_radius,
            0f
        ),
        typedArray.getDimension(
            R.styleable.JoySelectorLayout_joy_rt_corner_radius,
            0f
        ),
        typedArray.getDimension(
            R.styleable.JoySelectorLayout_joy_rb_corner_radius,
            0f
        ),
        typedArray.getDimension(
            R.styleable.JoySelectorLayout_joy_rb_corner_radius,
            0f
        ),
        typedArray.getDimension(
            R.styleable.JoySelectorLayout_joy_lb_corner_radius,
            0f
        ),
        typedArray.getDimension(
            R.styleable.JoySelectorLayout_joy_lb_corner_radius,
            0f
        )
    )
}

3.5 创建边框颜色与大小

这个很容易,直接读取属性值,代码如下

/**
 * 生成边框宽度
 */
private fun createStrokeWith(typedArray: TypedArray): Int {
    mStrokeWidth =
        typedArray.getDimension(
            R.styleable.JoySelectorLayout_joy_stroke_width, 0f
        ).toInt()
    return mStrokeWidth
}

/**
 * 生成边框颜色
 */
private fun createStrokeColor(typedArray: TypedArray): Int {
    mStrokeColor = typedArray.getColor(
        R.styleable.JoySelectorLayout_joy_stroke_color, 0
    )
    return mStrokeColor
}

3.6 创建形状样式

这里只有圆形跟矩形两种形状,原本连圆形也不想定义,毕竟矩形的宽度的一半当作圆角它不就是个圆吗,后来一想也不合适,如果这个矩形宽度随内容变化而变化,那我岂不是圆角也得跟着变吗,所以不如直接设置个圆形属性,按需选择形状,同样我们读取joy_shape_style属性,1代表矩形,2代码圆形,默认为矩形

/**
 * 创建样式
 */
private fun createShapetyle(typedArray: TypedArray): Int {
    shapeStyle = typedArray.getString(R.styleable.JoySelectorLayout_joy_shape_style)
    return if (TextUtils.equals("2", shapeStyle))
        GradientDrawable.RING
    else
        GradientDrawable.RECTANGLE
}

3.7 生成默认状态下的GradientDrawable背景

normalDrawables = createGradientDrawable(typedArray)
normalDrawables.apply {
    gradientType = GradientDrawable.LINEAR_GRADIENT
    cornerRadii = createRadius(typedArray)
    setStroke(createStrokeWith(typedArray), createStrokeColor(typedArray))
    shape = createShapetyle(typedArray)
}

点击状态的pressedDrawables与默认状态的设置完全一样,只是取的属性名称不同,这里不展开说明

3.8 创建水波纹效果

RippleDrawable的构造方法需要传入三个参数,第一个为ColorStateList,第二个content是作为基底的drawable,可以用之前的normalDrawable,也可以自定义一个,第三个mask,可控制水波纹范围的drawable

rippleDrawable = RippleDrawable(
    ColorStateList(
        arrayOf(
            intArrayOf(android.R.attr.state_pressed),
            intArrayOf(android.R.attr.state_focused),
            intArrayOf(android.R.attr.state_activated)
        ),
        intArrayOf(
            typedArray.getColor(R.styleable.JoySelectorLayout_joy_ripple_color, 0),
            typedArray.getColor(R.styleable.JoySelectorLayout_joy_ripple_color, 0),
            typedArray.getColor(R.styleable.JoySelectorLayout_joy_ripple_color, 0)
        )
    ),
    normalDrawables, ShapeDrawable()
)
background = rippleDrawable

xml配置示例

<com.coffee.android.JoySelectorLayout
    android:layout_width="match_parent"
    android:layout_height="100dp"
    android:layout_margin="10dp"
    android:clickable="true"
    android:focusable="true"
    app:joy_bg_color="@color/transparent"
    app:joy_corner_radius="10dp"
    app:joy_ripple="true"
    app:joy_ripple_color="@color/color_BBBBBB"
    app:joy_stroke_color="@color/teal_200"
    app:joy_stroke_width="1dp">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="设置水波纹效果"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</com.coffee.android.JoySelectorLayout>

3.9 添加点击效果

用StateListDrawable设置点击效果同xml基本很相似,也是每个state都要去设置个drawable属性,最后还要加个默认的drawable,无论哪种都要注意顺序,默认的drawable都要加在最后,这边就用我们之前定义好的pressedDrawable作为点击后的效果背景,normalDrawable作为默认的背景,代码如下

stateDrawable.addState(
    intArrayOf(
        android.R.attr.state_focused,
        android.R.attr.state_pressed,
        android.R.attr.state_enabled
    ), pressedDrawables
)
stateDrawable.addState(
    intArrayOf(android.R.attr.state_pressed),
    pressedDrawables
)
stateDrawable.addState(
    intArrayOf(android.R.attr.state_focused),
    pressedDrawables
)
stateDrawable.addState(
    intArrayOf(android.R.attr.state_enabled),
    normalDrawables
)
stateDrawable.addState(intArrayOf(), normalDrawables)

xml配置示例

<com.coffee.android.JoySelectorLayout
    android:layout_width="match_parent"
    android:layout_height="100dp"
    android:clickable="true"
    android:focusable="true"
    android:layout_margin="10dp"
    app:joy_bg_color="@color/transparent"
    app:joy_corner_radius="10dp"
    app:joy_pressed_end_color="@color/color_FCFCFC"
    app:joy_pressed_start_color="@color/color_BBBBBB"
    app:joy_pressed_stroke_color="@color/teal_200"
    app:joy_pressed_stroke_width="2dp"
    app:joy_stroke_color="@color/teal_200"
    app:joy_stroke_width="1dp">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="设置点击事件"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</com.coffee.android.JoySelectorLayout>

3.10 增加开关,切换水波纹跟点击效果

val needRipple = typedArray.getBoolean(R.styleable.JoySelectorLayout_joy_ripple, false)
background = if(needRipple) rippleDrawable else stateDrawable

3.11 完整代码

/**
 * Author: tanglei
 */
class JoySelectorLayout : ConstraintLayout {
    /**
     * 渲染背景,普通正常状态下的样式
     */
    private lateinit var normalDrawables: GradientDrawable

    /**
     * 渲染背景,点击状态下的样式
     */
    private lateinit var pressedDrawables: GradientDrawable

    /**
     * 状态背景,设置普通,点击状态的样式
     */
    private lateinit var stateDrawable: StateListDrawable

    /**
     * 水波纹背景
     */
    private lateinit var rippleDrawable: RippleDrawable

    /**
     * 样式,圆角矩形还是圆形
     */
    private var shapeStyle: String? = null

    /**
     * 边框大小
     */
    private var mStrokeWidth = 0

    /**
     * 边框颜色
     */
    private var mStrokeColor = 0


    constructor(context: Context) : super(context, null, 0) {
        initView(context, null, 0)
    }

    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs, 0) {
        initView(context, attrs, 0)
    }

    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr

    ) {
        initView(context, attrs, defStyleAttr)
    }


    private fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) {
        if (attrs != null) {
            normalDrawables = GradientDrawable()
            stateDrawable = StateListDrawable()

            val typedArray = context.obtainStyledAttributes(
                attrs, R.styleable.JoySelectorLayout, defStyleAttr, 0
            )
            normalDrawables = createGradientDrawable(typedArray)
            normalDrawables.apply {
                gradientType = GradientDrawable.LINEAR_GRADIENT
                cornerRadii = createRadius(typedArray)
                setStroke(createStrokeWith(typedArray), createStrokeColor(typedArray))
                shape = createShapetyle(typedArray)
            }

            pressedDrawables = createPressedGradientDrawable(typedArray)
            pressedDrawables.apply {
                gradientType = GradientDrawable.LINEAR_GRADIENT
                cornerRadii = createRadius(typedArray)
                setStroke(createPressedStrokeWith(typedArray), createPressedStrokeColor(typedArray))
                shape = createShapetyle(typedArray)
            }

            rippleDrawable = RippleDrawable(
                ColorStateList(
                    arrayOf(
                        intArrayOf(android.R.attr.state_pressed),
                        intArrayOf(android.R.attr.state_focused),
                        intArrayOf(android.R.attr.state_activated)
                    ),
                    intArrayOf(
                        typedArray.getColor(R.styleable.JoySelectorLayout_joy_ripple_color, 0),
                        typedArray.getColor(R.styleable.JoySelectorLayout_joy_ripple_color, 0),
                        typedArray.getColor(R.styleable.JoySelectorLayout_joy_ripple_color, 0)
                    )
                ),
                normalDrawables, ShapeDrawable()
            )

            stateDrawable.addState(
                intArrayOf(
                    android.R.attr.state_focused,
                    android.R.attr.state_pressed,
                    android.R.attr.state_enabled
                ), pressedDrawables
            )
            stateDrawable.addState(
                intArrayOf(android.R.attr.state_pressed),
                pressedDrawables
            )
            stateDrawable.addState(
                intArrayOf(android.R.attr.state_focused),
                pressedDrawables
            )
            stateDrawable.addState(
                intArrayOf(android.R.attr.state_enabled),
                normalDrawables
            )
            stateDrawable.addState(intArrayOf(), normalDrawables)

            val needRipple = typedArray.getBoolean(R.styleable.JoySelectorLayout_joy_ripple, false)
            background = if(needRipple) rippleDrawable else stateDrawable
            typedArray.recycle()
        }
    }

    /**
     * 创建圆弧半径数组
     */
    private fun createCornerArray(typedArray: TypedArray): FloatArray {
        return floatArrayOf(
            typedArray.getDimension(
                R.styleable.JoySelectorLayout_joy_lt_corner_radius,
                0f
            ),
            typedArray.getDimension(
                R.styleable.JoySelectorLayout_joy_lt_corner_radius,
                0f
            ),
            typedArray.getDimension(
                R.styleable.JoySelectorLayout_joy_rt_corner_radius,
                0f
            ),
            typedArray.getDimension(
                R.styleable.JoySelectorLayout_joy_rt_corner_radius,
                0f
            ),
            typedArray.getDimension(
                R.styleable.JoySelectorLayout_joy_rb_corner_radius,
                0f
            ),
            typedArray.getDimension(
                R.styleable.JoySelectorLayout_joy_rb_corner_radius,
                0f
            ),
            typedArray.getDimension(
                R.styleable.JoySelectorLayout_joy_lb_corner_radius,
                0f
            ),
            typedArray.getDimension(
                R.styleable.JoySelectorLayout_joy_lb_corner_radius,
                0f
            )
        )
    }

    /**
     * 创建样式
     */
    private fun createShapetyle(typedArray: TypedArray): Int {
        shapeStyle = typedArray.getString(R.styleable.JoySelectorLayout_joy_shape_style)
        return if (TextUtils.equals("2", shapeStyle))
            GradientDrawable.RING
        else
            GradientDrawable.RECTANGLE
    }


    /**
     * 生成边框宽度
     */
    private fun createStrokeWith(typedArray: TypedArray): Int {
        mStrokeWidth =
            typedArray.getDimension(
                R.styleable.JoySelectorLayout_joy_stroke_width, 0f
            ).toInt()
        return mStrokeWidth
    }

    /**
     * 生成边框颜色
     */
    private fun createStrokeColor(typedArray: TypedArray): Int {
        mStrokeColor = typedArray.getColor(
            R.styleable.JoySelectorLayout_joy_stroke_color, 0
        )
        return mStrokeColor
    }

    /**
     * 生成点击状态下边框宽度
     */
    private fun createPressedStrokeWith(typedArray: TypedArray): Int {
        return typedArray.getDimension(
            R.styleable.JoySelectorLayout_joy_pressed_stroke_width, 0f
        ).toInt()
    }

    /**
     * 生成点击状态下边框颜色
     */
    private fun createPressedStrokeColor(typedArray: TypedArray): Int {
        return typedArray.getColor(
            R.styleable.JoySelectorLayout_joy_pressed_stroke_color, 0
        )
    }

    /**
     * 决定用哪个方向的GradientDrawable
     */
    private fun createGradientDrawable(
        typedArray: TypedArray
    ): GradientDrawable {
        val direction = typedArray.getString(
            R.styleable.JoySelectorLayout_joy_direction
        )
        val colors = createColors(typedArray)

        return GradientDrawable(
            when (direction) {
                "2" -> GradientDrawable.Orientation.TOP_BOTTOM
                "3" -> GradientDrawable.Orientation.RIGHT_LEFT
                "4" -> GradientDrawable.Orientation.BOTTOM_TOP
                "5" -> GradientDrawable.Orientation.TL_BR
                "6" -> GradientDrawable.Orientation.TR_BL
                "7" -> GradientDrawable.Orientation.BL_TR
                "8" -> GradientDrawable.Orientation.BR_TL
                else -> GradientDrawable.Orientation.LEFT_RIGHT
            }, colors
        )
    }

    /**
     * 创建圆角
     */
    private fun createRadius(typedArray: TypedArray): FloatArray {
        val radius =
            typedArray.getDimension(R.styleable.JoySelectorLayout_joy_corner_radius, 0f)
        return if (radius != 0f)
            floatArrayOf(radius, radius, radius, radius, radius, radius, radius, radius)
        else
            createCornerArray(typedArray)
    }

    private fun createPressedGradientDrawable(typedArray: TypedArray): GradientDrawable {
        val direction = typedArray.getString(
            R.styleable.JoySelectorLayout_joy_pressed_direction
        )
        val colors = createPressedColors(typedArray)
        return when (direction) {
            "2" -> GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, colors)
            "3" -> GradientDrawable(GradientDrawable.Orientation.RIGHT_LEFT, colors)
            "4" -> GradientDrawable(GradientDrawable.Orientation.BOTTOM_TOP, colors)
            "5" -> GradientDrawable(GradientDrawable.Orientation.TL_BR, colors)
            "6" -> GradientDrawable(GradientDrawable.Orientation.TR_BL, colors)
            "7" -> GradientDrawable(GradientDrawable.Orientation.BL_TR, colors)
            "8" -> GradientDrawable(GradientDrawable.Orientation.BR_TL, colors)
            else -> GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, colors)
        }

    }

    private fun createPressedColors(typedArray: TypedArray): IntArray {
        val bgColor = typedArray.getColor(
            R.styleable.JoySelectorLayout_joy_pressed_bg_color, -1
        )
        val colors = if (bgColor != -1) {
            intArrayOf(bgColor, bgColor)
        } else {
            intArrayOf(
                typedArray.getColor(
                    R.styleable.JoySelectorLayout_joy_pressed_start_color,
                    0
                ),
                typedArray.getColor(
                    R.styleable.JoySelectorLayout_joy_pressed_end_color,
                    0
                )
            )
        }
        return colors
    }

    /**
     * 创建背景颜色
     */
    private fun createColors(typedArray: TypedArray): IntArray {
        var bgColor = typedArray.getColor(
            R.styleable.JoySelectorLayout_joy_bg_color, -1
        )
        val colors = if (bgColor != -1) {
            intArrayOf(bgColor, bgColor)
        } else {
            intArrayOf(
                typedArray.getColor(
                    R.styleable.JoySelectorLayout_joy_start_color,
                    0
                ),
                typedArray.getColor(
                    R.styleable.JoySelectorLayout_joy_end_color,
                    0
                )
            )
        }
        return colors
    }

    /**
     * 边框颜色,边框宽度默认为1像素
     *
     * @param color
     */
    fun setStrokeColor(color: Int) {
        normalDrawables.setStroke(mStrokeWidth, color)
        background = stateDrawable
    }

    /**
     * 边框颜色宽度都可以设置
     *
     * @param width
     * @param color
     */
    fun setStrokeColor(width: Int, color: Int) {
        mStrokeWidth = width
        setStrokeColor(color)
    }

    /**
     * 动态设置背景色,单色
     *
     * @param color
     */
    fun setBgColor(color: Int) {
        normalDrawables.setColor(color)
        background = stateDrawable
    }

    /**
     * 动态设置背景色,渐变色
     *
     * @param colors
     */
    fun setBgColors(colors: IntArray?) {
        normalDrawables.colors = colors
        background = stateDrawable
    }

}