Gradient Pages in Xamarin.Forms

Special thanks to the Xamarin community from which this post is based on: https://forums.xamarin.com/discussion/22440/gradient-as-background-color

Gradient Pages in Xamarin Forms

The objective is to have a page with a background color that transitions from one to another.

Show me the code!

First, create a simple page class that inherits from ContentPage:

public class GradientContentPageContentPage
{
    public Xamarin.Forms.Color StartColor { getset; }
    public Xamarin.Forms.Color EndColor { getset; }
}

You’re going to need a renderer in both Android and iOS which will draw the gradient on the GradientContentPage:

iOS:

[assemblyExportRenderer(typeof(GradientContentPage), typeof(GradientContentPageRenderer))]
namespace MyApp.iOS
{
    public class GradientContentPageRenderer : PageRenderer
    {
        protected override void OnElementChanged(VisualElementChangedEventArgs e)
        {
            base.OnElementChanged(e);
            if (e.OldElement != nullreturn;
            if (e.NewElement is GradientContentPage page)
            {
                var gradientLayer = new CAGradientLayer
                {
                    Frame = View.Bounds,
                    Colors = new CGColor[] {page.StartColor.ToCGColor(), page.EndColor.ToCGColor()}
                };
                View.Layer.InsertSublayer(gradientLayer, 0);
            }
        }
    }
}

And Android:

[assemblyExportRenderer(typeof(GradientContentPage), typeof(GradientContentPageRenderer))]
namespace MyApp.Droid
{
    public class GradientContentPageRenderer : PageRenderer
    {
        public GradientContentPageRenderer(Context context) : base(context)
        {
        }
 
        private Xamarin.Forms.Color StartColor { getset; }
        private Xamarin.Forms.Color EndColor { getset; }
        protected override void DispatchDraw(global::Android.Graphics.Canvas canvas)
        {
            var gradient = new Android.Graphics.LinearGradient(0, 0, 0, Height,
                this.StartColor.ToAndroid(),
                this.EndColor.ToAndroid(),
                Android.Graphics.Shader.TileMode.Mirror);
            var paint = new Android.Graphics.Paint()
            {
                Dither = true,
            };
            paint.SetShader(gradient);
            canvas.DrawPaint(paint);
            base.DispatchDraw(canvas);
        }
 
        protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
        {
            base.OnElementChanged(e);
 
            if (e.OldElement != null || Element == null)
            {
                return;
            }
 
            try
            {
                var page = e.NewElement as GradientContentPage;
                this.StartColor = page.StartColor;
                this.EndColor = page.EndColor;
            }
            catch (Exception ex)
            {
               //Publish the error
            }
        }
 
    }
}

Now that we have the renderers ready, add a new XAML page and base it on GradientContentPage:

public partial class LoginPage : GradientContentPage

In the XAML, you need to tell the XAML that the page is based on the custom page, not the standard page. Notice the xmlns:page code:

<page:GradientContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:page="clr-namespace:MyApp.Views.Common;assembly=MyApp"
             x:Class="MyApp.LoginPage"
             StartColor="DarkBlue"
             EndColor="LightBlue">

That’s it!

Advertisements

Platform Specific Pickers in Xamarin Forms

Here’s a handy shortcut on how to make your Pickers do some OS-specific behaviors.

Problem: By default, once you open an iOS Picker it will select the first item, even if you don’t press the Done button. You can tell iOS to only select when the Done is pressed.

Add this reference to the top of your XAML page:

xmlns:iOsSpecific="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"

Now you can tell the Picker to implement this iOS-only behaviour:

<Picker iOsSpecific:Picker.UpdateMode="WhenFinished"></Picker>

 

Xamarin Forms Binding Basics

Kind 1: Bind the CatName from the page’s Model set to the BindingContext:
<Label Text=”{Binding CatName}></Label>

Kind 2: Bind the CatName from a bindable property on the page control:

Add a Bindable CatName property to the page or control in the code behind:

public static BindableProperty CatNameProperty =
	BindableProperty.Create (
		nameof( CatName),
		typeof ( string ),
		typeof ( Badge ),
		defaultValue: "",
		defaultBindingMode: BindingMode.OneWay
	);

public string CatName{
	get { return ( string ) GetValue( CatNameProperty ); }
	set { SetValue ( CatNameProperty, value ); }
}

Then reference the CatName property on the control. Notice that the x:Name of the control is ‘CatLoveControl’:

<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="CoApp.Views.Common.CatBlock"
             x:Name="CatLoveControl">
    <ContentView.Content>
      <StackLayout>
         <Label Text="{Binding Source={x:Reference CatLoveControl}, Path=CatName}"/>
      </StackLayout>
    </ContentView.Content>
</ContentView>

 

Xamarin Data Triggers

Data triggers for beginners.

Let’s say we want to show a label indicating that the person retires this year if their age is 65.

First, we have a Model in the code behind which has an age field. We set that to the BindingContext:

public HumanResourcesApp()
{
    InitializeComponent();
    BindingContext = new Model() {Age = 65};
    .....

Now in the XAML we add a trigger that says: “When the Age is = 65 change the IsVisible to true”

<Label Text="You retire this year" IsVisible="False">
   <Label.Triggers>
        <DataTrigger Binding="{Binding Age}" TargetType="Label" Value="65">
               <Setter Property="IsVisible" Value="true"></Setter>
        </DataTrigger>
    </Label.Triggers>
</Label>

 

Xamarin Forms Email Validator

Yep, you need to validate an email address on your form. Here’s the easy way to do it.

First, add the NuGet Package “FormsToolKit” from James Montemagno.

Now add a reference to it in the header of your page:

2017-09-07 14_32_46-CoApp - Microsoft Visual Studio  (Administrator).png

Now, tell your Entry that it should use the EmailValidatorBehavour from the FormsToolKit

2017-09-07 14_33_53-CoApp - Microsoft Visual Studio  (Administrator).png

Now, add a label and tell it’s IsVisible to be triggered when the EmailValidator fires:

2017-09-07 14_34_53-CoApp - Microsoft Visual Studio  (Administrator).png

Now the Label will appear when the EmailValidator’s IsValid field is False

Converter Basics

So, you have your first XAML page up. Well done.

Let’s say your manager comes over and says that now when a user uses the app, if they are Canadian the app should show that they now get free Moose Butter.

Let’s have a look at one way we can skin this Moose. On a high level, your Model could have a new property that you could bind to the Page, perhaps a Label like this:

2017-09-07 14_08_49-CoApp - Microsoft Visual Studio  (Administrator).png

But that is not very re-usable. Instead we can simply ask the Model if the user is a Canadian and if so, show that text.

First we need a converter which will understand “Canada” as a country and the text to show.

2017-09-07 14_11_03-CoApp - Microsoft Visual Studio  (Administrator).png

It has two simple functions. We’ll just concentrate on the conversion of text “Convert”, not back and forth with “ConvertBack” It’s one way.

Now let’s add it to our form so that a Label can use it:

2017-09-07 14_13_17-CoApp - Microsoft Visual Studio  (Administrator).png

Then we can consume it:

2017-09-07 14_14_05-CoApp - Microsoft Visual Studio  (Administrator).png