Skip to content

Instantly share code, notes, and snippets.

@armanso
Last active April 17, 2021 14:14
Show Gist options
  • Save armanso/45a919063ea5a6b2d8e22e5564a3e0e9 to your computer and use it in GitHub Desktop.
Save armanso/45a919063ea5a6b2d8e22e5564a3e0e9 to your computer and use it in GitHub Desktop.
Part 2 of blog post - Control view's shadow
fun View.setShadow(
@ColorRes shadowColor: Int,
@DimenRes cornerRadius: Int,
@DimenRes elevation: Int,
shadowGravity: Int = Gravity.BOTTOM,
@ColorRes backgroundColorResource: Int = 0
) {
val resource = context.resources
val firstLayer = 0
val ratioTopBottom = 3
val defaultRatio = 2
if (background == null && backgroundColorResource == 0) {
throw RuntimeException("Pass backgroundColorResource or use setBackground")
}
if (background != null && background !is ColorDrawable) {
throw RuntimeException(
"${background::class.java.name} " +
"is not supported, set background as " +
"ColorDrawable or pass background as a resource"
)
}
val cornerRadiusValue = resource.getDimension(cornerRadius)
val elevationValue = resource.getDimension(elevation).toInt()
val shadowColorValue = ContextCompat.getColor(context, shadowColor)
val backgroundColor = if (backgroundColorResource != 0) {
ContextCompat.getColor(context, backgroundColorResource)
} else {
(background as ColorDrawable).color
}
val outerRadius = FloatArray(8) { cornerRadiusValue }
val directionOfY = when (shadowGravity) {
Gravity.CENTER -> 0
Gravity.TOP -> -1 * elevationValue / ratioTopBottom
Gravity.BOTTOM -> elevationValue / ratioTopBottom
else -> elevationValue / defaultRatio // Gravity.LEFT & Gravity.RIGHT
}
val directionOfX = when (shadowGravity) {
Gravity.LEFT -> -1 * elevationValue / ratioTopBottom
Gravity.RIGHT -> elevationValue / ratioTopBottom
else -> 0
}
val shapeDrawable = ShapeDrawable()
shapeDrawable.paint.color = backgroundColor
shapeDrawable.paint.setShadowLayer(
cornerRadiusValue / ratioTopBottom,
directionOfX.toFloat(),
directionOfY.toFloat(),
shadowColorValue
)
shapeDrawable.shape = RoundRectShape(outerRadius, null, null)
when (Build.VERSION.SDK_INT) {
in Build.VERSION_CODES.BASE..Build.VERSION_CODES.O_MR1 -> setLayerType(
View.LAYER_TYPE_SOFTWARE,
shapeDrawable.paint
)
}
val drawable = LayerDrawable(arrayOf(shapeDrawable))
drawable.setLayerInset(
firstLayer,
elevationValue,
elevationValue * defaultRatio,
elevationValue,
elevationValue * defaultRatio
)
background = drawable
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment