Summary of Chapter 27. Custom renderers
Note
This book was published in the spring of 2016, and has not been updated since then. There is much in the book that remains valuable, but some of the material is outdated, and some topics are no longer entirely correct or complete.
A Xamarin.Forms element such as Button
is rendered with a platform-specific button encapsulated in a class named ButtonRenderer
. Here is the iOS version of ButtonRenderer
, the Android version of ButtonRenderer
, and the UWP version of ButtonRenderer
.
This chapter discusses how you can write your own renderers to create custom views that map to platform-specific objects.
The complete class hierarchy
There are four assemblies that contain the Xamarin.Forms platform-specific code. You can view the source on GitHub using these links:
- Xamarin.Forms.Platform (very small)
- Xamarin.Forms.Platform.iOS
- Xamarin.Forms.Platform.Android
- Xamarin.Forms.Platform.UAP
Note
The WinRT
assemblies mentioned in the book are no longer part of this solution.
The PlatformClassHierarchy sample displays a class hierarchy for the assemblies that are valid for the executing platform.
You'll notice an important class named ViewRenderer
. This is the class you derive from when creating a platform-specific renderer. It exists in three different versions, because it's tied to the view system of the target platform:
The iOS ViewRenderer<TView, TNativeView>
has generic arguments:
TView
constrained toXamarin.Forms.View
TNativeView
constrained toUIKit.UIView
The Android ViewRenderer<TView, TNativeView>
has generic arguments:
TView
constrained toXamarin.Forms.View
TNativeView
constrained toAndroid.Views.View
The UWP ViewRenderer<TElement, TNativeElement>
has differently named generic arguments:
TElement
constrained toXamarin.Forms.View
TNativeElement
constrained toWindows.UI.Xaml.FrameworkElement
When writing a renderer, you will be deriving a class from View
, and then writing multiple ViewRenderer
classes, one for each supported platform. Each platform-specific implementation will reference a native class that derives from the type you specify as the TNativeView
or TNativeElement
parameter.
Hello, custom renderers!
The HelloRenderers program references a custom view named HelloView
in its App
class.
The HelloView
class is included in the HelloRenderers project and simply derives from View
.
The HelloViewRenderer
class in the HelloRenderers.iOS project derives from ViewRenderer<HelloView, UILabel>
. In the OnElementChanged
override, it creates a native iOS UILabel
and calls SetNativeControl
.
The HelloViewRenderer
class in the HelloRenderers.Droid project derives from ViewRenderer<HelloView, TextView>
. In the OnElementChanged
override, it creates an Android TextView
and calls SetNativeControl
.
The HelloViewRenderer
class in the HelloRenderers.UWP and other Windows projects derives from ViewRenderer<HelloView, TextBlock>
. In the OnElementChanged
override, it creates a Windows TextBlock
and calls SetNativeControl
.
All the ViewRenderer
derivatives contain an ExportRenderer
attribute on the assembly level that associates the HelloView
class with the particular HelloViewRenderer
class. This is how Xamarin.Forms locates renderers in the individual platform projects:
Renderers and properties
The next set of renderers implements ellipse drawing, and is located in the various projects of the Xamarin.FormsBook.Platform solution.
The EllipseView
class is in the Xamarin.FormsBook.Platform platform. The class is similar to BoxView
and defines just a single property: Color
of type Color
.
The renderers can transfer property values set on a View
to the native object by overriding the OnElementPropertyChanged
method in the renderer. Within this method (and within most of the renderer), two properties are available:
Element
, the Xamarin.Forms elementControl
, the native view or widget or control object
The types of these properties are determined by the generic parameters to ViewRenderer
. In this example, Element
is of type EllipseView
.
The OnElementPropertyChanged
override can therefore transfer the Color
value of the Element
to the native Control
object, probably with some kind of conversion. The three renderers are:
- iOS:
EllipseViewRenderer
, which uses anEllipseUIView
class for the ellipse. - Android:
EllipseViewRenderer
, which uses anEllipseDrawableView
class for the ellipse. - UWP:
EllipseViewRenderer
, which can use the native WindowsEllipse
class.
The EllipseDemo class displays several of these EllipseView
objects:
The BouncingBall bounces an EllipseView
off the sides of the screen.
Renderers and events
It is also possible for renderers to indirectly generate events. The StepSlider
class is similar to the normal Xamarin.Forms Slider
but allows specifying a number of discrete steps between the Minimum
and Maximum
values.
The three renderers are:
- iOS:
StepSliderRenderer
- Android:
StepSliderRenderer
- UWP:
StepSliderRenderer
The renderers detect changes to the native control, and then call SetValueFromRenderer
, which references a bindable property defined in the StepSlider
, a change to which causes the StepSlider
to fire a ValueChanged
event.
The StepSliderDemo sample demonstrates this new slider.