final Class<? extends Drawable> clazz = mClassLoader.loadClass(className).asSubclass(Drawable.class);
constructor = clazz.getConstructor();
CONSTRUCTOR_MAP.put(className, constructor);
}
}
return constructor.newInstance();
} catch (NoSuchMethodException e) {
...
}
代码完成由于创立shape等需求设置各种属性来构建,比较契合build设计形式,那我们首先封装build形式的shapeBuilder,这样做虽然代码比起直接运用apply{}要多,但是可以让纯java项目用起来很舒适,其他完成请查看源码:
class ShapeBuilder : DrawableBuilder {
private var mRadius = 0f
private var mWidth = 0f
private var mHeight = 0f
...
private var mShape = GradientDrawable.RECTANGLE
private var mSolidColor = 0
/**辨别设置四个角的圆角*/
fun corner(leftTop: Float,rightTop: Float,leftBottom: Float,rightBottom: Float): ShapeBuilder {
....if(dp)dp2px(leftTop) else leftTop
return this
}
fun solid(@ColorRes colorId: Int): ShapeBuilder {
mSolidColor = ContextCompat.getColor(context, colorId)
return this
}
// 省略其他参数设置办法 详细代码查看源码
override fun build(): Drawable {
val gradientDrawable = GradientDrawable()
gradientDrawable = GradientDrawable()
gradientDrawable.setColor(mSolidColor)
gradientDrawable.shape = mShape
....其他参数设置
return gradientDrawable
}
}
把build形式转换为dsl实际上一切的build形式都可以轻松转换为dsl写法:
inline fun shapeDrawable(builder: ShapeBuilder.() -> Unit): Drawable {
return ShapeBuilder().also(builder).build()
}
//运用办法
val drawable = shapeDrawable{
...
}
备注:dsl用法参见juejin.cn/post/695318… 中dsl小节
函数去括号经过下面封装曾经完成了dsl的写法,通常setBackground可以经过setter简化,但是我发现由于有些api设计还需求加括号,这样不太kotlin:
//容易阅读
iv1.background = shapeDrawable {
shape(ShapeBuilder.Shape.RECTANGLE)
solid("#ABE2E3")
}
//多了括号看起来不舒适
iv2.setImageDrawable(shapeDrawable {
solid("#84232323")
})
怎样去掉括号呢?有2种方式infix函数(中缀表达)和property setter
infix函数特点和标准:
Kotlin允许在不运用括号和点号的状况下调用函数
必须只要一个参数
必须是成员函数或扩展函数
不支持可变参数和带默许值参数
/**为一切ImageView添加扩展infix函数 来去掉括号*/
infix fun ImageView.src(drawable: Drawable?) {
this.setImageDrawable(drawable)
}
//运用如下
iv2 src shapeDrawable {
shape(ShapeBuilder.Shape.OVAL)
solid("#E3ABC2")
}
当然了代码是用来阅读的。团体以为假设我们少量运用infix函数,阅读困难会大大添加,所以建议函数命名必须可以直击函数功用,而且函数功用复杂且单一。
property setter方式,主要运用kotlin可以简化setter为 变量 =来去括号:
/**扩展变量*/
var ImageView.src: Drawable
get() = drawable
set(value) {
this.setImageDrawable(value)
}
//运用如下
iv2.src = shapeDrawable {
shape(ShapeBuilder.Shape.OVAL)
solid("#E3ABC2")
}
感谢@叮凛凛 指点,欢迎大家讨论一同窗习,共同提高。
优缺陷优点:
代码直接创立比起xml方式可以提升功用
dsl方式比起build形式和调用办法设置愈加繁复契合kotlin作风
经过适宜的代码管理可以复用这些代码,比xml管理方便
缺陷:
没有as的预览功用,只要经过上机观测
api还没有掩盖一切drawable属性(例如shape = ring等)
后语下面把的DrawableDsl基础用法引见完了,欢迎大家运用,欢迎提Issues,记得给个star哦。Github链接:https://github.com/forJrking/DrawableDsl
(责任编辑:admin)