Wednesday 4 April 2018

DatePicker Placeholder & Border Style using CustomRenderer

Introduction
In Xamarin.Forms there is no Placeholder,  BorderRadius, BorderColor, BorderWidth for DatePicker Control. So in this article, we can learn how to set those properties for DatePicker using CustomRenderer.
Requirements
  • This article source code is prepared by using Visual Studio. And it is better to install the latest Visual Studio updates from here.
  • This article is prepared on a MAC machine.
  • This sample project is Xamarin.Forms PCL project.
  • This sample app is targeted for Android, iOS. And tested for Android & iOS.
Description
The creation of a Xamarin.Forms project is very simple in Visual Studio for Mac. It will create three projects:
  1. Shared Code
  2. Xamarin.Android
  3. Xamarin.iOS
The Mac system with Visual Studio for Mac doesn't support Windows projects (UWP, Windows, Windows Phone).
The following steps will show you how to create Xamarin.Forms projects in a Mac system with Visual Studio.
First, open Visual Studio. And click on New Project.

After that, we need to select whether you're doing Xamarin.Forms or Xamarin.Android or Xamarin.iOS project. If we want to create Xamarin.Forms project just follow the below screenshot.

Then, we have to give the app name; i.e., DatePickerDefaultTextDemo.

Note:
In the above screen under Shared Code, select Portable class Library or Use Shared Library.
Then, click on Next Button and the following screenshot will be displayed. In that screen, we have to browse the file path where we want to save that application on our PC.

After clicking on the create button it will create the DatePickerDefaultTextDemo Xamarin.Forms project like below.

And the project structure will be:
DatePickerDefaultTextDemo:  It is for Shared Code
DatePickerDefaultTextDemo.Droid:  It is for Android.
DatePickerDefaultTextDemo.iOS:  It is for iOS

    Now follow the below steps=>

    Portable Class Library (PCL)


    Step 1:
    In PCL, create a class name DatePickerCtrl inside the CustomControls folder and which should inherit any DatePicker like below.

    DatePickerCtrl.cs

    1. using Xamarin.Forms;  
    2.   
    3. namespace DatePickerDefaultTextDemo.CustomControls  
    4. {  
    5.     public class DatePickerCtrl : DatePicker  
    6.     {  
    7.         public static readonly BindableProperty EnterTextProperty = BindableProperty.Create(propertyName: "Placeholder", returnType: typeof(string), declaringType: typeof(DatePickerCtrl), defaultValue: default(string));  
    8.         public string Placeholder { getset; }  
    9.     }  
    10. }  

    Added a Bindable property for DatePicker placeholder in above class.  


    Step 2:

    Create your own Xaml page named DatePickerTextPage.xaml inside the Views folder and make sure to refer to "DatePickerCtrl" class in Xaml by declaring a namespace for its location and using the namespace prefix on the control element. The following code example shows how the "DatePickerCtrl" renderer class can be consumed by a Xaml page:
    DatePickerTextPage.xaml

    1. <?xml version="1.0" encoding="utf-8"?>    
    2. <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"   
    3.    BackgroundColor="White"  
    4.     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"   
    5.     xmlns:custom="clr-namespace:DatePickerDefaultTextDemo.CustomControls;assembly=DatePickerDefaultTextDemo"  
    6.     x:Class="DatePickerDefaultTextDemo.Views.DatePickerTextPage">    
    7.     <StackLayout VerticalOptions="Start" Padding="25" >   
    8.         <custom:DatePickerCtrl x:Name="datePicker" Placeholder="Select Date of birth" HeightRequest="45"  HorizontalOptions="FillAndExpand"/>    
    9.     </StackLayout>    
    10. </ContentPage>   
    Note:
    The "custom" namespace prefix can be named anything. However, the clr-namespace and assembly values must match the details of the custom renderer class. Once the namespace is declared the prefix is used to reference the custom control.

    DatePickerTextPage.xaml.cs
    1. using Xamarin.Forms;  
    2.   
    3. namespace DatePickerDefaultTextDemo.Views  
    4. {  
    5.     public partial class DatePickerTextPage : ContentPage  
    6.     {  
    7.         public DatePickerTextPage()  
    8.         {  
    9.             InitializeComponent();  
    10.         }  
    11.     }  
    12. }  

    Xamarin.Andriod
    In Android project, create a class and add the code like below

    DatePickerCtrlRenderer.cs
    1. using System;  
    2. using Android.Graphics;  
    3. using Android.Graphics.Drawables;  
    4. using DatePickerDefaultTextDemo.CustomControls;  
    5. using DatePickerDefaultTextDemo.Droid;  
    6. using Xamarin.Forms;  
    7. using Xamarin.Forms.Platform.Android;  
    8.   
    9. [assembly: ExportRenderer(typeof(DatePickerCtrl), typeof(DatePickerCtrlRenderer))]  
    10. namespace DatePickerDefaultTextDemo.Droid  
    11. {  
    12.     public class DatePickerCtrlRenderer : DatePickerRenderer  
    13.     {  
    14.         protected override void OnElementChanged(ElementChangedEventArgs<DatePicker> e)  
    15.         {  
    16.             base.OnElementChanged(e);  
    17.             this.Control.SetTextColor(Android.Graphics.Color.Rgb(83,63,149));  
    18.             this.Control.SetBackgroundColor(Android.Graphics.Color.Transparent);  
    19.             this.Control.SetPadding(20,0,0,0);  
    20.   
    21.             GradientDrawable gd = new GradientDrawable();  
    22.             gd.SetCornerRadius(25); //increase or decrease to changes the corner look  
    23.             gd.SetColor(Android.Graphics.Color.Transparent);  
    24.             gd.SetStroke(3, Android.Graphics.Color.Rgb(83, 63, 149));  
    25.   
    26.             this.Control.SetBackgroundDrawable(gd);  
    27.   
    28.             DatePickerCtrl element = Element as DatePickerCtrl;  
    29.   
    30.             if (!string.IsNullOrWhiteSpace(element.Placeholder))  
    31.             {  
    32.                 Control.Text = element.Placeholder;  
    33.             }  
    34.   
    35.             this.Control.TextChanged += (sender, arg) => {  
    36.                 var selectedDate = arg.Text.ToString();  
    37.                 if (selectedDate == element.Placeholder)  
    38.                 {  
    39.                     Control.Text = DateTime.Now.ToString("dd/MM/yyyy");  
    40.                 }  
    41.             };  
    42.         }  
    43.     }  
    44. }  

    The call to the base class's OnElementChanged method instantiates an Android DatePicker, with a reference to the control being assigned to the renderer's property. And assigned below properties and Events for DatePicker.
    Properties:
    1. BorderWidth
    2. SetStroke
    3. SetCornerRadius
    4. SetColor 
    5. SetPadding
    6.   Placeholder text
    Events:
    1. TextChanged
    Output:

    Xamarin.iOS
    In iOS project, create a class and add the code like below

    DatePickerCtrlRenderer.cs
    1. using System;  
    2. using DatePickerDefaultTextDemo.CustomControls;  
    3. using DatePickerDefaultTextDemo.iOS;  
    4. using UIKit;  
    5. using Xamarin.Forms;  
    6. using Xamarin.Forms.Platform.iOS;  
    7.   
    8. [assembly: ExportRenderer(typeof(DatePickerCtrl), typeof(DatePickerCtrlRenderer))]  
    9. namespace DatePickerDefaultTextDemo.iOS  
    10. {  
    11.     public class DatePickerCtrlRenderer : DatePickerRenderer  
    12.     {  
    13.         protected override void OnElementChanged(ElementChangedEventArgs<DatePicker> e)  
    14.         {  
    15.             base.OnElementChanged(e);  
    16.   
    17.             if (this.Control == null)  
    18.                 return;  
    19.             var element = e.NewElement as DatePickerCtrl;  
    20.             if (!string.IsNullOrWhiteSpace(element.Placeholder)){  
    21.                 Control.Text = element.Placeholder;  
    22.             }  
    23.             Control.BorderStyle = UITextBorderStyle.RoundedRect;  
    24.             Control.Layer.BorderColor = UIColor.FromRGB(83,63,149).CGColor;  
    25.             Control.Layer.CornerRadius = 10;  
    26.             Control.Layer.BorderWidth = 1f;  
    27.             Control.AdjustsFontSizeToFitWidth = true;  
    28.             Control.TextColor = UIColor.FromRGB(83, 63, 149);  
    29.   
    30.             Control.ShouldEndEditing +=(textField) => {  
    31.                 var seletedDate = (UITextField)textField;  
    32.                 var text = seletedDate.Text;  
    33.                 if(text==element.Placeholder)  
    34.                 {  
    35.                     Control.Text = DateTime.Now.ToString("dd/MM/yyyy");  
    36.                 }  
    37.                 return true;  
    38.             };  
    39.         }  
    40.   
    41.         private void OnCanceled(object sender, EventArgs e)  
    42.         {  
    43.             Control.ResignFirstResponder();  
    44.         }  
    45.   
    46.         private void OnDone(object sender, EventArgs e)  
    47.         {  
    48.             Control.ResignFirstResponder();  
    49.         }  
    50.     }  
    51. }  
    The call to the base class's method OnElementChanged instantiates an iOS control UIDatePicker, with a reference to the control being assigned to the renderer's property Control. And assigned below properties and Events for DatePicker.
    Properties:
    1. BorderStyle
    2. BorderColor
    3. CornerRadius
    4. BorderWidth 
    5.   Placeholder text
    Events:
    1. ShouldEndEditing
    2. OnDone
    3. OnCanceled
    Output:

     

    Note: 
    If you want set  Placeholder text, CornerRadius, BorderStyle for TimePicker follow the steps like above. 
    Common properties for every Control in Xamarin.Forms CustomRenderer.

    Android:

    1. this.Control.SetTextColor(Android.Graphics.Color.Rgb(83,63,149));  
    2. this.Control.SetBackgroundColor(Android.Graphics.Color.Transparent);  
    3. this.Control.SetPadding(20,0,0,0);  
    4.   
    5. GradientDrawable gd = new GradientDrawable(); 
    6.  
    7. gd.SetCornerRadius(25); //increase or decrease to changes the corner look  
    8. gd.SetColor(Android.Graphics.Color.Transparent);  
    9. gd.SetStroke(3, Android.Graphics.Color.Rgb(83, 63, 149));  
    10. this.Control.SetBackgroundDrawable(gd);  
    e.t.c.,

    iOS:

    1. Control.BorderStyle = UITextBorderStyle.RoundedRect;  
    2. Control.Layer.BorderColor = UIColor.FromRGB(83,63,149).CGColor;  
    3. Control.Layer.CornerRadius = 10;  
    4. Control.Layer.BorderWidth = 1f;  
    5. Control.AdjustsFontSizeToFitWidth = true;  
    6. Control.TextColor = UIColor.FromRGB(83, 63, 149);  
    e.t.c.,

    Please download the sample from below.


    No comments:

    Post a Comment