Create a Xamarin.Forms Visual Renderer
Xamarin.Forms Visual enables renderers to be created and selectively applied to VisualElement
objects, without having to subclass Xamarin.Forms views. A renderer that specifies an IVisual
type, as part of its ExportRendererAttribute
, will be used to render opted in views, rather than the default renderer. At renderer selection time, the Visual
property of the view is inspected and included in the renderer selection process.
Important
Currently the Visual
property cannot be changed after the view has been rendered, but this will change in a future release.
The process for creating and consuming a Xamarin.Forms Visual renderer is:
- Create platform renderers for the required view. For more information, see Create renderers.
- Create a type that derives from
IVisual
. For more information, see Create an IVisual type. - Register the
IVisual
type as part of theExportRendererAttribute
that decorates the renderers. For more information, see Register the IVisual type. - Consume the Visual renderer by setting the
Visual
property on the view to theIVisual
name. For more information, see Consume the Visual renderer. - [optional] Register a name for the
IVisual
type. For more information, see Register a name for the IVisual type.
Create platform renderers
For information about creating a renderer class, see Custom Renderers. However, note that a Xamarin.Forms Visual renderer is applied to a view without having to subclass the view.
The renderer classes outlined here implement a custom Button
that displays its text with a shadow.
iOS
The following code example shows the button renderer for iOS:
public class CustomButtonRenderer : ButtonRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
// Cleanup
}
if (e.NewElement != null)
{
Control.TitleShadowOffset = new CoreGraphics.CGSize(1, 1);
Control.SetTitleShadowColor(Color.Black.ToUIColor(), UIKit.UIControlState.Normal);
}
}
}
Android
The following code example shows the button renderer for Android:
public class CustomButtonRenderer : Xamarin.Forms.Platform.Android.AppCompat.ButtonRenderer
{
public CustomButtonRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
// Cleanup
}
if (e.NewElement != null)
{
Control.SetShadowLayer(5, 3, 3, Color.Black.ToAndroid());
}
}
}
Create an IVisual type
In your cross-platform library, create a type that derives from IVisual
:
public class CustomVisual : IVisual
{
}
The CustomVisual
type can then be registered against the renderer classes, permitting Button
objects to opt into using the renderers.
Register the IVisual type
In the platform projects, add the ExportRendererAttribute
at the assembly level:
[assembly: ExportRenderer(typeof(Xamarin.Forms.Button), typeof(CustomButtonRenderer), new[] { typeof(CustomVisual) })]
namespace VisualDemos.iOS
{
public class CustomButtonRenderer : ButtonRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
// ...
}
}
}
In this example for the iOS platform project, the ExportRendererAttribute
specifies that the CustomButtonRenderer
class will be used to render consuming Button
objects, with the IVisual
type registered as the third argument. A renderer that specifies an IVisual
type, as part of its ExportRendererAttribute
, will be used to render opted in views, rather than the default renderer.
Consume the Visual renderer
A Button
object can opt into using the renderer classes by setting its Visual
property to Custom
:
<Button Visual="Custom"
Text="CUSTOM BUTTON"
BackgroundColor="{StaticResource PrimaryColor}"
TextColor="{StaticResource SecondaryTextColor}"
HorizontalOptions="FillAndExpand" />
Note
In XAML, a type converter removes the need to include the "Visual" suffix in the Visual
property value. However, the full type name can also be specified.
The equivalent C# code is:
Button button = new Button { Text = "CUSTOM BUTTON", ... };
button.Visual = new CustomVisual();
At renderer selection time, the Visual
property of the Button
is inspected and included in the renderer selection process. If a renderer isn't located, the Xamarin.Forms default renderer will be used.
The following screenshots show the rendered Button
, which displays its text with a shadow:
Register a name for the IVisual type
The VisualAttribute
can be used to optionally register a different name for the IVisual
type. This approach can be used to resolve naming conflicts between different Visual libraries, or in situations where you just want to refer to a Visual by a different name than its type name.
The VisualAttribute
should be defined at the assembly level in either the cross-platform library, or in the platform project:
[assembly: Visual("MyVisual", typeof(CustomVisual))]
The IVisual
type can then be consumed through its registered name:
<Button Visual="MyVisual"
... />
Note
When consuming a Visual through its registered name, any "Visual" suffix must be included.