Platform effects

Platform effects are used to simplify native control customization, reducing the need to create CustomRenderers for small styling changes. This means we don't have to create a custom renderer every single time we want native customization. To implement a PlatformEffect, we first create a class that subclasses the PlatformEffect framework. Then we have to write platform-specific implementations for each.

Following is a small overview of how the rendering process will look among the different projects:

Platform effects

Let's add a new folder called Effects inside the Camera project, add in a new file called LabelShadowEffect.cs, and implement the following:

public class LabelShadowEffect : RoutingEffect 
    { 
        #region Public Properties 
 
        public float Radius { get; set; } 
 
        public Color Color { get; set; } 
 
        public float DistanceX { get; set; } 
 
        public float DistanceY { get; set; } 
 
        #endregion 
 
        #region Constructors 
 
        public LabelShadowEffect() : base("Camera.LabelShadowEffect") 
        { 
        } 
 
        #endregion 
    } 

Our LabelShadowEffect must inherit the PlatformEffect framework. The Radius property is responsible for the corner radius of the shadow. Then we have the Color property that will set the color of the shadow. Finally, we have the DistanceX and DistanceY properties for assigning the position of the shadow.

Now we must create the platform implementations. Let's start with iOS, add in a new folder called Effects, add in a new file called LabelShadowEffectiOS.cs, and implement the following:

public class LabelShadowEffectiOS : PlatformEffect 
    { 
        #region Protected Methods 
 
        protected override void OnAttached() 
        { 
            try 
            { 
                var effect = (LabelShadowEffect)Element.Effects.FirstOrDefault(e => e is LabelShadowEffect); 
 
                if (effect != null) 
                { 
                    Control.Layer.CornerRadius = effect.Radius; 
                    Control.Layer.ShadowColor = effect.Color.ToCGColor(); 
                    Control.Layer.ShadowOffset = new CGSize(effect.DistanceX, effect.DistanceY); 
                    Control.Layer.ShadowOpacity = 1.0f; 
                } 
            } 
            catch (Exception ex) 
            { 
                Console.WriteLine("Cannot set property on attached control. Error: ", ex.Message); 
            } 
        } 
 
        protected override void OnDetached() 
        { 
        } 
 
        #endregion 
    } 

All PlatformEffects must override the OnAttached and OnDetached methods. The OnAttached method is where we set up all native shadow effects. We start with retrieving the first PlatformEffect from the Effects list of the Element object. Like our CustomRenderers, we have access to the original Xamarin.Forms element that we are customizing. In the OnDetached method, we would normally dispose any objects that are no longer required.

We must also add assembly lines above the namespace block like the following:

[assembly: Xamarin.Forms.ResolutionGroupName("Camera")] 
[assembly: Xamarin.Forms.ExportEffect(typeof(Camera.Droid.Effects.LabelShadowEffectiOS), "LabelShadowEffect")] 

We must add a ResolutionGroupName to specify the namespace for the effects; this prevents collisions with other effects of the same name. We also add the ExportEffect attribute to register the effect with a unique ID that is used by Xamarin.Forms, along with the group name, to locate the effect prior to applying it to a control.

Now let's add the equivalent for Android. Add a new folder in the Camera.Droid project, add a new file called LabelShadowEffectDroid.cs, and implement the following:

public class LabelShadowEffectDroid : PlatformEffect 
    { 
        #region Protected Methods 
 
        protected override void OnAttached() 
        { 
            try 
            { 
                var control = Control as Android.Widget.TextView; 
 
                var effect = (LabelShadowEffect)Element.Effects.FirstOrDefault(e => e is LabelShadowEffect); 
 
                if (effect != null) 
                { 
                    control.SetShadowLayer(effect.Radius, effect.DistanceX, effect.DistanceY, effect.Color.ToAndroid()); 
                } 
            } 
            catch (Exception ex) 
            { 
                Console.WriteLine("Cannot set property on attached control. Error: ", ex.Message); 
            } 
        } 
 
        protected override void OnDetached() 
        { 
        } 
 
        #endregion 
    }  

In our Android implementation, we start with retrieving the control as a native TextView. We then retrieve the first LabelShadowEffect object from the list of effects from the Element. We then use the method SetShadowLayer to create native shadowing on the TextView.

Great! Now we have our native implementations, let's add the DescriptionLabel object to the MainPage:

<Label x:Name="DesciptionLabel" Text="{Binding DescriptionMessage}" TextColor="Black"  
                    HorizontalOptions="Center" Font="Arial, 20" Grid.Row="1" Grid.Column="0"> 
                <Label.Effects> 
                    <e:LabelShadowEffect Radius="5" DistanceX="5" DistanceY="5"> 
                        <e:LabelShadowEffect.Color> 
                            <OnPlatform x:TypeArguments="Color" iOS="Black" Android="Blue" WinPhone="Red" /> 
                        </e:LabelShadowEffect.Color> 
                    </e:LabelShadowEffect> 
                </Label.Effects> 
            </Label> 

Here we are able to attach the effect inside our XAML. We must also add the namespace to the Effects folder:

xmlns:e="clr-namespace:Camera.Effects;assembly=Camera"  

This is how the MainPage will look once complete:

Platform effects
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.107.100