Shadow Constraint Layout with Round Corners
ConstraintLayout
with its own shadow and we will apply round corners around it just like CardView
Few Good things:
- No need to put
ConstraintLayout
insideCardView
anymore - You can draw custom shadows as well
- Use same technique with any view
Prequisites (Good if you know these things otherwise don’t worry):
Canvas
x,y corrdinatePorterDuffXfermode
Paint
classPath
class
Things we need to do
- Draw shadow
- Draw a border around the view
- Clip the view with RoundRorners
- Fill your view with white color: so you can see the border & shadow & you must draw this over your shadow paint
Draw shadow around your view
Classes required
Paint
: to paint with shadow colorPath
: To give a path to shadow and that is around the view like a RECTANGLE
val porterDuffXfermode = PorterDuffXfermode(PorterDuff.Mode.SRC)
val blurMaskFilter = BlurMaskFilter(blurRadius, BlurMaskFilter.Blur.NORMAL)
shadowPaint.xfermode = porterDuffXfermode
shadowPaint.maskFilter = blurMaskFilter
The shadow is blurry that’s why we have used blurMaskFilter. And blurMaskFilter will only blur your color The shadow should not overlap the content of your constraint layout that’s why we used PorterDuffXfermode
Now we setting up paint is completed. We have to give it a path and that’s a rectangle
So the we are going to write something like this.
- Goto to start point
- Make a rectangle from there and at last come back from where you started
- shadowPath.goToStartPosition()
- shadowPath.move_to_top_left_from_top_right
- shadowPath.move_to_bottom_left_from_top_left
- shadowPath.move_to_bottom_right_from_bottom_left
- shadowPath.move_to_top_right_from_bottom_right
"->" denotes : From
shadowPath.moveTo(width, 0f) //Top Right
shadowPath.lineTo(0, 0) // TR -> TL
shadowPath.lineTo(0,height) // TL -> BL
shadowPath.lineTo(width,height) // BL -> BR
shadowPath.lineTo(width, shadowStartY) // BR -> TR
Cool the paint and path are set. We just need to pass commands to draw it on canvas
canvas.drawPath(shadowPath, shadowPaint)
That’s it.. This is what you will see
Rectangular shadow
The toughest part is done, now only comes the easy part
Draw a border around the view
We are using canvas.drawRoundRect(rect,paint)
to draw. It requires a Rect
and paint
and we have provided both
Clip the view with RoundRorners
At the end we doing
canvas.clipPath(clipPath)
This means we want to clip this part(defined via clipPath) of canvas. And out future drawing commands must happen within the bounds of this clipPath
In real app we will do something like this
class MyLayout:View {
fun override fun dispatchDraw(canvas: Canvas) {
clipRoundCorners(canvas)
super.dispatchDraw(canvas)
}
Our job is to draw round corners around our view and also ensure your child views should not be drawn on that area. So we should write this function inside dispatchDraw. We can change the canvas before a child is drawn : https://developer.android.com/reference/android/view/ViewGroup.html#dispatchDraw(android.graphics.Canvas)
Fill your view with white color
Code should look pretty straight forward.
canvas.drawRoundRect(rectBackgroundRectF, cornerRadius, cornerRadius, rectPaint)
The paint
object has rectPaint.xfermode = porterDuffXfermode
, to ensure the paint should come on top of shadow
Final code should be like this
class MyLayout:View {
override fun dispatchDraw(canvas: Canvas) {
clipRoundCorners(canvas)
super.dispatchDraw(canvas)
}
override fun onDraw(canvas: Canvas){
drawShadow(canvas)
drawBorder(canvas)
drawRectBackground(canvas)
super.onDraw(canvas)
}
}
Full source code:
Full code snipet and how to use
1 very importatnt thing you have to do this in your parent view
android:clipChildren="false"
android:clipToPadding="false"
From these two commands we are telling the Android that parent view must not clip the views of ShadowConstraintLayot if the views are getting drawn outside of its bouds.
This is the final result..
Left one is Card View & Right one is ShadowConstraintLayout
You can play with blurRadius
property and also set shadow top
,bottom
,start
,end
offset
to suit your needs.