I talked in a previous post about creating box-shadows on iOS UIViews
that are transparent that you can find here: Xamarin.Tips – iOS Shadow on Transparent UIView
This is the Android counterpart! Let’s look at putting some shadows around a view with a fully transparent background. Android presented some completely different challenges compared to iOS. In the iOS solution, we ran into issues with Shadow layers requiring something in front of it to draw the drop shadow. With Android, using a CardView
from the design support library gives us access to the Elevation
and CardElevation
properties which CAN indeed give us shadows around our view even though it is transparent. However, that kills any border on the view. Remember that we are looking for a transparent view, with a solid border, and shadows around it.
The general approach for iOS was to draw two new layers with shadows around the right and bottom sides of the UIView
. Using layers allowed us to draw outside the actual frame of the view. However, with iOS, we aren’t so lucky.
So here’s the idea:
1. Adjust the margin and padding to allow us to expand the frame of the view
2. Draw a shadow gradient on the right side
3. Draw a shadow gradient on the bottom side
4. Draw a border around what our inner frame was
Here’s what that looks like in a custom renderer (since the origin of this was a custom Xamarin.Forms view):
TransparentFrameRenderer.cs
[assembly: ExportRenderer(typeof(TransparentFrame), typeof(TransparentFrameRenderer))] namespace YOUR_ANDROID_NAMESPACE { public class TransparentFrameRenderer : Xamarin.Forms.Platform.Android.AppCompat.FrameRenderer { protected override void OnElementChanged(ElementChangedEventArgs<Frame> e) { base.OnElementChanged(e); if (e.NewElement != null) { Element.Margin = new Thickness(-5); Element.Padding = new Thickness(15); Control.CardElevation = 0; Control.PreventCornerOverlap = false; } } protected override void OnDraw(Canvas canvas) { base.OnDraw(canvas); // draw border var strokePaint = new Paint(); strokePaint.SetARGB(255, 255, 255, 255); strokePaint.SetStyle(Paint.Style.Stroke); strokePaint.StrokeWidth = 2; var rect = canvas.ClipBounds; var outline = new Rect(15, 15, rect.Right - 15, rect.Bottom - 15); var bottomPaint = new Paint(); bottomPaint.SetStyle(Paint.Style.Fill); var shadowShader = new LinearGradient(0, 0, 0, 30, new Android.Graphics.Color(0, 0, 0, 100), new Android.Graphics.Color(0, 0, 0, 0), Shader.TileMode.Mirror); bottomPaint.SetShader(shadowShader); var rightPaint = new Paint(); rightPaint.SetStyle(Paint.Style.Fill); var rightShader = new LinearGradient(0, 0, 20, 0, new Android.Graphics.Color(0, 0, 0, 100), new Android.Graphics.Color(0, 0, 0, 0), Shader.TileMode.Mirror); rightPaint.SetShader(rightShader); // draw the bottom and right shadows canvas.DrawRect(12, rect.Bottom - 12, rect.Right - 12, rect.Bottom + 3, bottomPaint); canvas.DrawRect(rect.Right - 12, 14, rect.Right + 3, rect.Bottom, rightPaint); canvas.DrawRect(outline, strokePaint); } } }
Look at the Draw
override. We are setting up 3 different paints. The first is the Paint
for our white border. bottomPaint
sets up for our bottom shadow using a LinearGradient
as the shader, and similarly, rightPaint
sets up our shadow for the right side.
Finally, we call DrawRect
for both our shadows, then our border. The values in the DrawRect
calls for the shadows are just examples to play with padding and size values. You can play with those as you see fit to make your view look best.
I’ve tested this in some large ListViews
to test against the classic Android overdraw issue that can happen, but because it consists of 3 pretty simple strokes, I haven’t run into any performance issues. Hopefully this solution works for you!
This is NOT a complete solution, or a real reusable control, but more of a general approach to rendering shadows around a control with a transparent background.
If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!
One thought on “Xamarin.Tips – Android Shadows on Transparent Views”