Drawable代码化,减少你的XML

4,677 阅读3分钟

前言

之前在写项目的时候,少说都要有二三十个Drawable文件,不同的渐变,不同的圆角。每次要修改这个样式的时候,就需要找到这个XML,这个这个控件,然后再点到这个Drawable,有时候,还可能牵一发而动全身,别的地方也改动了。 所以,就想着写一个工具类,来简化这一步骤。

初始化

我们通常写圆角、渐变都是在 <gradient/> 标签下加的属性,所以我们今天的主角就是GradientDrawable

填充颜色

        /**
         * 填充颜色
         * @param fillColor 填充颜色
         */
        fun setFillColor(fillColor: Any): Builder {
            gradientDrawable?.setColor(DisplayUtil.colorConvert(App.Context, fillColor))
            return this
        }

描边颜色

        /**
         * 描边颜色
         * @param strokeColor 描边颜色
         * @param strokeWidth 描边粗细
         */
        fun setStrokeColor(strokeColor: Any, strokeWidth: Int): Builder {
            gradientDrawable?.setStroke(
                DisplayUtil.dp2px(strokeWidth),
                DisplayUtil.colorConvert(App.Context, strokeColor),
                0f,
                0f
            )
            return this
        }

统一圆角

        /**
         * 圆角
         */
        fun setRadius(radius: Int): Builder {
            gradientDrawable?.cornerRadius = DisplayUtil.dp2px(radius).toFloat()
            return this
        }

分别设置圆角

        /**
         * 单独设置圆角
         */
        fun setAroundRadius(
            topLeftRadius: Int,
            topRightRadius: Int,
            bottomRightRidus: Int,
            bottomLeftRidus: Int
        ): Builder {
            gradientDrawable?.cornerRadii = floatArrayOf(
                DisplayUtil.dp2px(topLeftRadius).toFloat(),
                DisplayUtil.dp2px(topLeftRadius).toFloat(),
                DisplayUtil.dp2px(topRightRadius).toFloat(),
                DisplayUtil.dp2px(topRightRadius).toFloat(),
                DisplayUtil.dp2px(bottomRightRidus).toFloat(),
                DisplayUtil.dp2px(bottomRightRidus).toFloat(),
                DisplayUtil.dp2px(bottomLeftRidus).toFloat(),
                DisplayUtil.dp2px(bottomLeftRidus).toFloat()
            )
            return this
        }

虚线

         /**
         * 虚线
         * @param strokeWidth 线宽度
         * @param dashColor   虚线颜色
         * @param dashWidth   虚线长度
         * @param dashGap     虚线间隔
         * @param shapeType   虚线类型
         *                   GradientDrawable#LINE      线
         *                   GradientDrawable#OVAL      椭圆
         *                   GradientDrawable#RECTANGLE 矩形
         *
         */
        fun setDash(
            strokeWidth: Int,
            dashColor: Any,
            dashWidth: Int,
            dashGap: Int,
            shapeType: Int = GradientDrawable.LINE
        ): Builder {
            gradientDrawable?.apply {
                setStroke(
                    DisplayUtil.dp2px(strokeWidth),
                    DisplayUtil.colorConvert(App.Context, dashColor),
                    DisplayUtil.dp2px(dashWidth).toFloat(),
                    DisplayUtil.dp2px(dashGap).toFloat()
                )
                shape = shapeType
            }
            return this
        }

这里的虚线只是横线,如果是竖线我还是通过XML来实现的。竖线的和弦就是通过旋转,把横线旋转90°

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:left="-100dp"
        android:right="-100dp">
        <rotate
            android:fromDegrees="90"
            android:visible="true">
            <shape android:shape="line">
                <stroke
                    android:width="1dp"
                    android:color="@color/red"
                    android:dashWidth="6dp"
                    android:dashGap="4dp" />
            </shape>
        </rotate>
    </item>
</layer-list>

渐变色

这里的渐变色,我们操作的对象时GradientDrawableorientation 这个属性API提供了8种方向,分别是

  • 上到下
  • 下到上
  • 左到右
  • 右到左
  • 左上到右下
  • 右下到左下
  • 右上到左下
  • 左下到右上
        //渐变色
        fun setShadow(
            orientation: GradientDrawable.Orientation,
            startColor: Any,
            endColor: Any
        ): Builder {
            //如果需要渐变色需要在第一个调用
            gradientDrawable = GradientDrawable(
                orientation, intArrayOf(
                    DisplayUtil.colorConvert(App.Context, startColor),
                    DisplayUtil.colorConvert(App.Context, endColor)
                )
            )
            return this
        }

至此,UI的三大法宝:阴影、渐变和圆角,我们已经搞定了两个。阴影的话,我们的UI比较可爱,没有太多阴影,有的话,要么使用layer-list要么就是切图。

完整源码


class ViewShapeUtil {

    class Builder {
        private var gradientDrawable: GradientDrawable? = null
        private var viewShapeUtil: ViewShapeUtil? = null

        init {
            gradientDrawable = GradientDrawable()
            viewShapeUtil = ViewShapeUtil()
        }

        /**
         * 填充颜色
         * @param fillColor 填充颜色
         */
        fun setFillColor(fillColor: Any): Builder {
            gradientDrawable?.setColor(DisplayUtil.colorConvert(App.Context, fillColor))
            return this
        }

        /**
         * 描边颜色
         * @param strokeColor 描边颜色
         * @param strokeWidth 描边粗细
         */
        fun setStrokeColor(strokeColor: Any, strokeWidth: Int): Builder {
            gradientDrawable?.setStroke(
                DisplayUtil.dp2px(strokeWidth),
                DisplayUtil.colorConvert(App.Context, strokeColor),
                0f,
                0f
            )
            return this
        }

        /**
         * 圆角
         */
        fun setRadius(radius: Int): Builder {
            gradientDrawable?.cornerRadius = DisplayUtil.dp2px(radius).toFloat()
            return this
        }

        /**
         * 单独设置圆角
         */
        fun setAroundRadius(
            topLeftRadius: Int,
            topRightRadius: Int,
            bottomRightRidus: Int,
            bottomLeftRidus: Int
        ): Builder {
            gradientDrawable?.cornerRadii = floatArrayOf(
                DisplayUtil.dp2px(topLeftRadius).toFloat(),
                DisplayUtil.dp2px(topLeftRadius).toFloat(),
                DisplayUtil.dp2px(topRightRadius).toFloat(),
                DisplayUtil.dp2px(topRightRadius).toFloat(),
                DisplayUtil.dp2px(bottomRightRidus).toFloat(),
                DisplayUtil.dp2px(bottomRightRidus).toFloat(),
                DisplayUtil.dp2px(bottomLeftRidus).toFloat(),
                DisplayUtil.dp2px(bottomLeftRidus).toFloat()
            )
            return this
        }

        /**
         * 虚线
         * @param strokeWidth 线宽度
         * @param dashColor   虚线颜色
         * @param dashWidth   虚线长度
         * @param dashGap     虚线间隔
         * @param shapeType   虚线类型
         *                   GradientDrawable#LINE
         *                   GradientDrawable#OVAL
         *                   GradientDrawable#RECTANGLE
         *                   GradientDrawable#RING
         *
         */
        fun setDash(
            strokeWidth: Int,
            dashColor: Any,
            dashWidth: Int,
            dashGap: Int,
            shapeType: Int = GradientDrawable.LINE
        ): Builder {
            gradientDrawable?.apply {
                setStroke(
                    DisplayUtil.dp2px(strokeWidth),
                    DisplayUtil.colorConvert(App.Context, dashColor),
                    DisplayUtil.dp2px(dashWidth).toFloat(),
                    DisplayUtil.dp2px(dashGap).toFloat()
                )
                shape = shapeType
            }
            return this
        }

        //渐变色
        fun setShadow(
            orientation: GradientDrawable.Orientation,
            startColor: Any,
            endColor: Any
        ): Builder {
            //因为这个是new 出来的,所以.这个调用需要在第一个
            gradientDrawable = GradientDrawable(
                orientation, intArrayOf(
                    DisplayUtil.colorConvert(App.Context, startColor),
                    DisplayUtil.colorConvert(App.Context, endColor)
                )
            )
            return this
        }

        fun show(tagView: View): ViewShapeUtil {
            tagView.background = gradientDrawable
            return viewShapeUtil!!
        }
    }
}

颜色转换

    /**
     * 颜色转换
     *
     * @param color
     * @return
     */
    fun colorConvert(context: Context?, color: Any): Int {
        if (color is String) {
            return Color.parseColor(color.toString())
        }
        return if (color is Int) {
            ContextCompat.getColor(context!!, color)
        } else R.color.colorAccent
    }

本文,主要是介绍通过代码设置View的背景样式。如文中有错误,还望指正,感谢。欢迎讨论