Customising iOS Frame shadows in Xamarin.Forms 4.5+
Even with iOS 13 having been out for quite a while now and Xamarin.Forms 4.5+ bringing a lot of improvements and fixes, I still find myself having to customise things for different projects (usually for the same reason as some of my other other posts: Graphic Designers and marketing people 😂).
One thing that was immediately picked up on one project when the upgrade to Xamarin.Forms 4.5+ was finally kicked off, was the frame shadows suddenly looked quite pronounced was the shadows on Frames compared to what used to look quite different with some tweaks:
Now customising the shadows on iOS isn’t a new thing, however suddenly the renderers I had in place to control this just stopped working and the designers insisting it be fixed or the planned technical upgrades should not be allowed to proceed, which at the time was not an option given Apple’s April 2020 deadline* for no UIWebView’s (which requires Xamarin.Forms 4.5+) and apps to target iOS 13.
Prior to Xamarin.Forms 4.5 the following code was working quite nicely:
// Update shadow to match better material design standards of elevation
Since upgrading though, this code effectively did nothing to the UI. After some digging it turns out the renderer has changed and now the shadow is its own UIView. To customise the shadow now we need to find that view in the renderer and then apply some slightly different code to it so we can can customise how the shadow should look (which is a matter of opinion) for Frames.
I fiddled with a few ways and there’s no saying this is the best approach, but until more customisation in Xamarin.Forms is available, this is how I was able to get around things fairly painlessly and get out an updated product for my client:
This renders things out in a more “correct way” (designer term not mine). Correct/cleaner/prettier, whatever you want to call it, using the above code you should be able to customise Frame shadows to whatever requirements you have on your project from simple more card view aligned views to bright Lime areas of fuzziness.
One thing to note about this approach is that it will render for all Frame instances, which may not be desirable, as such I more often than not take the approach of quickly bundling things into a custom control so you have more control over where this is used as well as being able to implement bindable properties to customise things:
// You could also implement bindable properties such as the
// following (or even better take all this code and submit a PR
// to Xamarin.Forms for everyone, unfortunately I don't have
/// Make iOS frame shadows look more natural than the default Xamarin.Forms implementation
You could take the same approach with Effect’s, but honestly I find Renderers far more versatile and robust over the longer term.
So that’s it from me on that one, hopefully this helps some of you who have similar requirements that I did and saves you the reading and trial and error I went through.
As usual, if you want the entire working example, please have a look here on GitHub.
* Note: Due to the 2020 COVID-19 crisis Apple relaxed the deadlines for the new requirements, however at time of writing this doesn’t remove the need altogether so the update work has to be done regardless.
Edit 8-Apr-2020: After a round of testing I was advised on screens that needed to manipulate Frame’s (e.g. show/hide, expand collapse etc) things were reverting to the default implementation and causing some other elements to look incorrect. Article updated to reflect this.
Matt has been developing software for over 17 years and these days specialises in cross-platform app development. He's developed dozens of apps on several of the app stores with apps hitting #1.
Matt's worked for large software companies and enterprise organisations, the Australian government as well as various startups on cutting edge technology.
Originally from New Zealand, Matt currently lives in Brisbane with his wife, daughter and two dogs.