package com.angcyo.tablayout import android.content.res.ColorStateList import android.content.res.Resources import android.graphics.Canvas import android.graphics.Color import android.graphics.ColorFilter import android.graphics.drawable.Drawable import android.graphics.drawable.GradientDrawable import android.os.Build import androidx.annotation.IntDef import java.util.* /** * 用来构建GradientDrawable * Email:angcyo@126.com * @author angcyo * @date 2019/11/27 * Copyright (c) 2019 ShenZhen O&M Cloud Co., Ltd. All rights reserved. */ open class DslGradientDrawable : AbsDslDrawable() { /**形状*/ @Shape var gradientShape = GradientDrawable.RECTANGLE /**填充的颜色*/ var gradientSolidColor = Color.TRANSPARENT /**边框的颜色*/ var gradientStrokeColor = Color.TRANSPARENT /**边框的宽度*/ var gradientStrokeWidth = 0 /**蚂蚁线的宽度*/ var gradientDashWidth = 0f /**蚂蚁线之间的间距*/ var gradientDashGap = 0f /** * 四个角, 8个设置点的圆角信息 * 从 左上y轴->左上x轴->右上x轴->右上y轴..., 开始设置. */ var gradientRadii = floatArrayOf(0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f) /**颜色渐变*/ var gradientColors: IntArray? = null var gradientColorsOffsets: FloatArray? = null /**渐变中心点坐标*/ var gradientCenterX = 0.5f var gradientCenterY = 0.5f /**渐变半径, 非比例值, 是px值. [GradientDrawable.RADIAL_GRADIENT]类型才有效*/ var gradientRadius = 0.5f /** 渐变方向, 默认从左到右 */ var gradientOrientation = GradientDrawable.Orientation.LEFT_RIGHT /** 渐变类型 */ @GradientType var gradientType = GradientDrawable.LINEAR_GRADIENT /**真正绘制的[Drawable]*/ var originDrawable: Drawable? = null /**宽度补偿*/ var gradientWidthOffset: Int = 0 /**高度补偿*/ var gradientHeightOffset: Int = 0 /**当前的配置, 是否能生成有效的[GradientDrawable]*/ open fun isValidConfig(): Boolean { return gradientSolidColor != Color.TRANSPARENT || gradientStrokeColor != Color.TRANSPARENT || gradientColors != null } fun _fillRadii(array: FloatArray, radii: String?) { if (radii.isNullOrEmpty()) { return } val split = radii.split(",") if (split.size != 8) { throw IllegalArgumentException("radii 需要8个值.") } else { val dp = Resources.getSystem().displayMetrics.density for (i in split.indices) { array[i] = split[i].toFloat() * dp } } } fun fillRadii(radius: Float) { Arrays.fill(gradientRadii, radius) } fun fillRadii(radius: Int) { _fillRadii(gradientRadii, radius.toFloat()) } fun _fillRadii(array: FloatArray, radius: Float) { Arrays.fill(array, radius) } fun _fillRadii(array: FloatArray, radius: Int) { _fillRadii(array, radius.toFloat()) } fun _fillColor(colors: String?): IntArray? { if (colors.isNullOrEmpty()) { return null } val split = colors.split(",") return IntArray(split.size) { val str = split[it] if (str.startsWith("#")) { Color.parseColor(str) } else { str.toInt() } } } /**构建或者更新[originDrawable]*/ open fun updateOriginDrawable(): GradientDrawable? { val drawable: GradientDrawable? = when (originDrawable) { null -> GradientDrawable() is GradientDrawable -> originDrawable as GradientDrawable else -> { null } } drawable?.apply { bounds = this@DslGradientDrawable.bounds shape = gradientShape setStroke( gradientStrokeWidth, gradientStrokeColor, gradientDashWidth, gradientDashGap ) setColor(gradientSolidColor) cornerRadii = gradientRadii if (gradientColors != null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { setGradientCenter( this@DslGradientDrawable.gradientCenterX, this@DslGradientDrawable.gradientCenterY ) } gradientRadius = this@DslGradientDrawable.gradientRadius gradientType = this@DslGradientDrawable.gradientType if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { orientation = gradientOrientation } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { setColors(gradientColors, gradientColorsOffsets) } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { colors = gradientColors } } originDrawable = this invalidateSelf() } return drawable } open fun configDrawable(config: DslGradientDrawable.() -> Unit): DslGradientDrawable { this.config() updateOriginDrawable() return this } override fun draw(canvas: Canvas) { super.draw(canvas) originDrawable?.apply { setBounds( this@DslGradientDrawable.bounds.left - gradientWidthOffset / 2, this@DslGradientDrawable.bounds.top - gradientHeightOffset / 2, this@DslGradientDrawable.bounds.right + gradientWidthOffset / 2, this@DslGradientDrawable.bounds.bottom + gradientHeightOffset / 2 ) draw(canvas) } } // /** * 4个角, 8个点 圆角配置 */ fun cornerRadii(radii: FloatArray) { gradientRadii = radii } fun cornerRadius(radii: Float) { Arrays.fill(gradientRadii, radii) } fun cornerRadius( leftTop: Float = 0f, rightTop: Float = 0f, rightBottom: Float = 0f, leftBottom: Float = 0f ) { gradientRadii[0] = leftTop gradientRadii[1] = leftTop gradientRadii[2] = rightTop gradientRadii[3] = rightTop gradientRadii[4] = rightBottom gradientRadii[5] = rightBottom gradientRadii[6] = leftBottom gradientRadii[7] = leftBottom } /** * 只配置左边的圆角 */ fun cornerRadiiLeft(radii: Float) { gradientRadii[0] = radii gradientRadii[1] = radii gradientRadii[6] = radii gradientRadii[7] = radii } fun cornerRadiiRight(radii: Float) { gradientRadii[2] = radii gradientRadii[3] = radii gradientRadii[4] = radii gradientRadii[5] = radii } fun cornerRadiiTop(radii: Float) { gradientRadii[0] = radii gradientRadii[1] = radii gradientRadii[2] = radii gradientRadii[3] = radii } fun cornerRadiiBottom(radii: Float) { gradientRadii[4] = radii gradientRadii[5] = radii gradientRadii[6] = radii gradientRadii[7] = radii } // // override fun setColorFilter(colorFilter: ColorFilter?) { super.setColorFilter(colorFilter) originDrawable?.colorFilter = colorFilter } override fun setTintList(tint: ColorStateList?) { super.setTintList(tint) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { originDrawable?.setTintList(tint) } } override fun setState(stateSet: IntArray): Boolean { return originDrawable?.setState(stateSet) ?: super.setState(stateSet) } override fun getState(): IntArray { return originDrawable?.state ?: super.getState() } // } @IntDef( GradientDrawable.RECTANGLE, GradientDrawable.OVAL, GradientDrawable.LINE, GradientDrawable.RING ) @kotlin.annotation.Retention(AnnotationRetention.SOURCE) annotation class Shape @IntDef( GradientDrawable.LINEAR_GRADIENT, GradientDrawable.RADIAL_GRADIENT, GradientDrawable.SWEEP_GRADIENT ) @kotlin.annotation.Retention(AnnotationRetention.SOURCE) annotation class GradientType /**快速创建[GradientDrawable]*/ fun dslGradientDrawable(action: DslGradientDrawable.() -> Unit): GradientDrawable { return DslGradientDrawable().run { action() updateOriginDrawable()!! } }