A Xamarin Forms Renderer provides the device-specific logic to display a Xamarin Forms control using platform-native UI. Traditionally this was done using the ViewRenderer<T,T> base class. What this actually creates in the UI hierarchy is two controls – the outer being a basic place-holder providing layout logic and the inner control being the desired native control (e.g. a UITextField in the case of an Entry on iOS).
This introduces overhead into the UI and complicates the layout logic as the whole page is arranged. The concept of a fast renderer does away with the enclosing ViewRenderer and instead requires you to implement an interface with the standard behaviour required by the Xamarin Forms layout system.
When I began re-writing my MediaElement for inclusion into Xamarin Forms I needed to replace the iOS renderer with a fast renderer but there was very little documentation on building a fast renderer. I found looking through the source for other renderers helpful. The Pages and WebView all use fast renderers in the current codebase.
On iOS this interface is IVisualElementRenderer and it exposes a number of properties, an event and a few methods.
- Element – returns the Xamarin Forms element which this renderer represents
- NativeView – returns the native UIView-based control
- NativeViewController – returns the UIViewController which manages the View
- ElementChanged – raised when an Element is assigned to the renderer
- GetDesiredSize – returns a SizeRequest from a set of constraints. The control can alter this to fit required content for example. An extension method for UIView provides GetSizeRequest which will calculate the SizeRequest based on the constraints and optional minimum width/height.
- SetElement – assigns the Element and causes the ElementChanged event to be raised. You’ll also hook up the PropertyChanged event here to react to changes in the Element and apply them to the NativeView.
- SetElementSize – updates the layout to fit a specific size. Normally you call Layout.LayoutChildIntoBoundingRegion() to perform this.
A secondary interface IEffectControlProvider provides a single method to register an effect with the View.
By looking at the existing in-box renderers I was able to understand how they are implemented and re-write the MediaElementRenderer to use this pattern. For reference the full code of the iOS renderer is here in GitHub.
Not all the renderers in iOS use the new approach, I imagine it will be some time before all the existing renderers are re-written. Currently UWP and other platforms still use the traditional approach. I’ll follow up with the Android equivalent soon.