android 使用setShadowLayer创建简单的阴影
android 使用setShadowLayer创建简单的阴影现在Android项目使用阴影的需求越来越多了,下面我价绍一下创建阴影的代码。一般来说ui切图的阴影虽然好看舒服一点,但是不利于动态定制,如果代码里能自己定制多好啊。主要的使用的api是paint.setShaodwLayout。/*** 设置简单的阴影*/class SimpleShadowBuilder {private var s
·
android 使用setShadowLayer创建简单的阴影
现在Android项目使用阴影的需求越来越多了,下面我价绍一下创建阴影的代码。一般来说ui切图的阴影虽然好看舒服一点,但是不利于动态定制,如果代码里能自己定制多好啊。主要的使用的api是paint.setShaodwLayout。
/**
* 设置简单的阴影
*/
class SimpleShadowBuilder {
private var shadowRadius: Float = 2f.dpToPxFloat()
private var solidColor: Int = Color.WHITE
private var shadowColor: Int = Color.DKGRAY
private var dx = 0f
private var dy = 0f
private var width: Int = -1
private var height: Int = -1
private var shape: Shape = OvalShape()
fun setShadowRadius(shadowRadius: Float): SimpleShadowBuilder {
this.shadowRadius = shadowRadius.coerceAtLeast(0f)
return this
}
fun setShadowColor(color: Int): SimpleShadowBuilder {
shadowColor = color
return this
}
fun setSolidColor(color: Int): SimpleShadowBuilder {
this.solidColor = color
return this
}
fun setShadowDx(dx: Float): SimpleShadowBuilder {
this.dx = dx
return this
}
fun setShadowDy(dy: Float): SimpleShadowBuilder {
this.dy = dy
return this
}
fun width(width: Int): SimpleShadowBuilder {
this.width = width
return this
}
fun height(height: Int): SimpleShadowBuilder {
this.height = height
return this
}
fun setShape(shape: Shape): SimpleShadowBuilder {
this.shape = shape
return this
}
fun roundShape(cornerRadius: Float): SimpleShadowBuilder {
val outerRadius = floatArrayOf(
cornerRadius, cornerRadius, cornerRadius, cornerRadius,
0f, 0f, 0f, 0f
)
this.shape = RoundRectShape(outerRadius, null, null)
return this
}
private fun build(): Drawable {
val shadowDrawable = ShapeDrawable()
val paint = shadowDrawable.paint
paint.style = Paint.Style.FILL
paint.color = solidColor
paint.isAntiAlias = true
paint.isFilterBitmap = true
paint.isDither = true
paint.setShadowLayer(
shadowRadius,
dx.coerceAtMost(shadowRadius),
dy.coerceAtMost(shadowRadius),
shadowColor
)
shadowDrawable.shape = this.shape
var contentDr: Drawable = shadowDrawable
if (strokeWidth > 0 && strokeColor != Color.TRANSPARENT) {
val gradientDrawable = GradientDrawable()
gradientDrawable.setColor(Color.TRANSPARENT)
gradientDrawable.setStroke(strokeWidth, strokeColor)
if (shape is RoundRectShape && outerRadius != null) {
val target = FloatArray(8)
outerRadius?.copyInto(target)
gradientDrawable.cornerRadii = target
}
contentDr = LayerDrawable(arrayOf(shadowDrawable, gradientDrawable))
}
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
InsetDrawable(contentDr, shadowRadius)
} else {
InsetDrawable(contentDr, shadowRadius.toInt())
}
}
fun into(view: View) {
val parent = view.parent as? ViewGroup
parent?.clipChildren = false
parent?.clipToPadding = false
view.setLayerType(View.LAYER_TYPE_SOFTWARE, null)
val background = build()
view.post {
val shapeDr = (background as InsetDrawable).drawable
val inset = ceil(shadowRadius).toInt()
val dxInt = dx.toInt().coerceAtMost(inset)
val dyInt = dy.toInt().coerceAtMost(inset)
shapeDr?.setBounds(
inset - dxInt,
inset - dyInt,
(view.measuredWidth - inset) - dxInt,
(view.measuredHeight - inset - dyInt)
)
}
view.background = background
}
}
下面贴上使用效果
总的来说,上述方法虽然简单易用,但是存在一定的局限性,会导致硬件加速被关闭。在一些简单的情境下,可以尝试使用该方法。但是如果想要达到更好的效果,建议使用 Google 的 MaterialShapeDrawable。然而,笔者在实践中发现,即便使用 MaterialShapeDrawable,效果也并不是十分理想。希望未来能够找到更加令人满意的解决方案。
如果大家有更好的方案,可以一起讨论一下哦。
更多推荐
已为社区贡献1条内容
所有评论(0)