Ask or search…


Xamarin.Forms user interfaces are rendered using the native controls of the target platform, allowing Xamarin.Forms applications to retain the appropriate look and feel for each platform. Effects allow the native controls on each platform to be customized without having to resort to a custom renderer implementation.

Using Effects in Fabulous.XamarinForms

The recommended way to use an effect in Fabulous is by using the dedicated View.Effect. This control accepts the effect’s exported full name ("SomeResolutionGroup.SomeEffectName") and it can be attached to any control with the effects properties.
View.Button(effects = [
View.Effect(name = "SomeResolutionGroup.SomeEffectName")
This way is only suitable if your effect doesn’t need any external values.

Create wrapper for custom effects with properties

If you want to use your own effects with properties in Fabulous.XamarinForms, you will need to write an extension. For more information, please read about View Extensions
Let’s take this ShadowEffect for example:
open Xamarin.Forms
type ShadowEffect() =
inherit RoutingEffect("FabulousXamarinForms.ShadowEffect")
member val Radius = 0. with get, set
member val Color = Color.Default with get, set
member val DistanceX = 0. with get, set
member val DistanceY = 0. with get, set
If we want to use it in our views, we will need to write the following extension:
module ShadowEffectViewExtension =
open Fabulous
open Fabulous.XamarinForms
let RadiusAttribKey = AttributeKey "ShadowEffectRadius"
let ColorAttribKey = AttributeKey "ShadowEffectColor"
let DistanceXAttribKey = AttributeKey "ShadowEffectDistanceX"
let DistanceYAttribKey = AttributeKey "ShadowEffectDistanceY"
type Fabulous.XamarinForms.View with
static member inline ShadowEffect(?radius, ?color, ?distanceX, ?distanceY) =
let attribCount = 0
let attribCount = match radius with Some _ -> attribCount + 1 | None -> attribCount
let attribCount = match color with Some _ -> attribCount + 1 | None -> attribCount
let attribCount = match distanceX with Some _ -> attribCount + 1 | None -> attribCount
let attribCount = match distanceY with Some _ -> attribCount + 1 | None -> attribCount
let attribs = AttributesBuilder(attribCount)
match radius with None -> () | Some v -> attribs.Add(RadiusAttribKey, v)
match color with None -> () | Some v -> attribs.Add(ColorAttribKey, v)
match distanceX with None -> () | Some v -> attribs.Add(DistanceXAttribKey, v)
match distanceY with None -> () | Some v -> attribs.Add(DistanceYAttribKey, v)
let create () = ShadowEffect()
let update (prevOpt: ViewElement voption) (source: ViewElement) (target: ShadowEffect) =
source.UpdatePrimitive(prevOpt, target, RadiusAttribKey, (fun target v -> target.Radius <- v))
source.UpdatePrimitive(prevOpt, target, ColorAttribKey, (fun target v -> target.Color <- v))
source.UpdatePrimitive(prevOpt, target, DistanceXAttribKey, (fun target v -> target.DistanceX <- v))
source.UpdatePrimitive(prevOpt, target, DistanceYAttribKey, (fun target v -> target.DistanceY <- v))
ViewElement.Create(create, update, attribs)
This then enables us to use it like this:
View.Label(effects = [
View.ShadowEffect(color = Color.Black, radius = 5.)
Alternatively you can do it without an extension, and use both the created event and the Effects collection of the Xamarin.Forms control.
View.Label(created = fun e ->
let effect = new ShadowEffect()
effect.Color <- Color.Black
effect.Radius <- 5.
e.Effects.Add effect
This way is not recommended because it can’t make use of the incremental update mecanism.