Skip to content

Instantly share code, notes, and snippets.

@farukaf
Last active May 29, 2021 16:08
Show Gist options
  • Save farukaf/3f5f1891f27963f828d223cd498d9538 to your computer and use it in GitHub Desktop.
Save farukaf/3f5f1891f27963f828d223cd498d9538 to your computer and use it in GitHub Desktop.
Nullable DatePicker Xamarin - Update from jrgcubano
using System;
using System.Collections.Generic;
using System.Text;
using Xamarin.Forms;
namespace NullableDateAPP.Controls
{
public class NullableDatePicker : DatePicker
{
public NullableDatePicker() : base()
{
}
/// <summary>
/// The font property
/// </summary>
public static readonly BindableProperty FontProperty =
BindableProperty.Create("Font", typeof(Font), typeof(NullableDatePicker), new Font());
/// <summary>
/// The NullableDate property
/// </summary>
public static readonly BindableProperty NullableDateProperty =
BindableProperty.Create("NullableDate", typeof(DateTime?), typeof(NullableDatePicker), null, BindingMode.TwoWay);
/// <summary>
/// The XAlign property
/// </summary>
public static readonly BindableProperty XAlignProperty =
BindableProperty.Create("XAlign", typeof(TextAlignment), typeof(NullableDatePicker),
TextAlignment.Start);
/// <summary>
/// The HasBorder property
/// </summary>
public static readonly BindableProperty HasBorderProperty =
BindableProperty.Create("HasBorder", typeof(bool), typeof(NullableDatePicker), true);
/// <summary>
/// The Placeholder property
/// </summary>
public static readonly BindableProperty PlaceholderProperty =
BindableProperty.Create("Placeholder", typeof(string), typeof(NullableDatePicker), string.Empty, BindingMode.OneWay);
/// <summary>
/// The PlaceholderTextColor property
/// </summary>
public static readonly BindableProperty PlaceholderTextColorProperty =
BindableProperty.Create("PlaceholderTextColor", typeof(Color), typeof(NullableDatePicker), Color.Default);
/// <summary>
/// Gets or sets the Font
/// </summary>
public Font Font
{
get { return (Font)GetValue(FontProperty); }
set { SetValue(FontProperty, value); }
}
/// <summary>
/// Get or sets the NullableDate
/// </summary>
public DateTime? NullableDate
{
get { return (DateTime?)GetValue(NullableDateProperty); }
set
{
if (value != NullableDate)
{
SetValue(NullableDateProperty, value);
UpdateDate();
}
}
}
/// <summary>
/// Gets or sets the X alignment of the text
/// </summary>
public TextAlignment XAlign
{
get { return (TextAlignment)GetValue(XAlignProperty); }
set { SetValue(XAlignProperty, value); }
}
/// <summary>
/// Gets or sets if the border should be shown or not
/// </summary>
public bool HasBorder
{
get { return (bool)GetValue(HasBorderProperty); }
set { SetValue(HasBorderProperty, value); }
}
/// <summary>
/// Get or sets the PlaceHolder
/// </summary>
public string Placeholder
{
get { return (string)GetValue(PlaceholderProperty); }
set { SetValue(PlaceholderProperty, value); }
}
/// <summary>
/// Sets color for placeholder text
/// </summary>
public Color PlaceholderTextColor
{
get { return (Color)GetValue(PlaceholderTextColorProperty); }
set { SetValue(PlaceholderTextColorProperty, value); }
}
protected override void OnBindingContextChanged()
{
base.OnBindingContextChanged();
UpdateDate();
}
protected override void OnPropertyChanged(string propertyName = null)
{
base.OnPropertyChanged(propertyName);
if (propertyName == DateProperty.PropertyName)
{
NullableDate = Date;
}
if (propertyName == NullableDateProperty.PropertyName)
{
if (NullableDate.HasValue)
{
Date = NullableDate.Value;
OnPropertyChanged(DateProperty.PropertyName);
}
}
}
private void UpdateDate()
{
if (NullableDate.HasValue)
{
Date = NullableDate.Value;
}
else
{
Date = DateTime.Today;
}
}
}
}
using UIKit;
using Xamarin.Forms;
namespace NullableDateAPP.iOS.Extensions
{
/// <summary>
/// Color extensions
/// </summary>
public static class CheckColorExtensions
{
internal static readonly UIColor SeventyPercentGrey = new UIColor(0.7f, 0.7f, 0.7f, 1);
public static bool IsDefault(this Color color) => Color.Default == color;
}
}
using Android.Views;
using System.ComponentModel;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using NullableDateAPP.Droid.Renderer;
using Android.Content;
using NullableDateAPP.Controls;
using System;
using Android.App;
using System.Globalization;
[assembly: ExportRenderer(typeof(NullableDatePicker), typeof(NullableDatePickerRenderer))]
namespace NullableDateAPP.Droid.Renderer
{
public class NullableDatePickerRenderer : DatePickerRenderer
{
public NullableDatePickerRenderer(Context context): base(context)
{
}
protected override DatePickerDialog CreateDatePickerDialog(int year, int month, int day)
{
var dialog = base.CreateDatePickerDialog(year, month, day);
//capture OK click
dialog.DateSet += Dialog_DateSet;
return dialog;
}
private void Dialog_DateSet(object sender, DatePickerDialog.DateSetEventArgs e)
{
var view = (NullableDatePicker)Element;
view.NullableDate = view.Date;
}
protected override void OnElementChanged(ElementChangedEventArgs<DatePicker> e)
{
base.OnElementChanged(e);
//Remove line under input
Control?.SetBackgroundColor(Android.Graphics.Color.Transparent);
var view = Element as NullableDatePicker;
if (view != null)
{
SetFont(view);
SetTextAlignment(view);
// SetBorder(view);
SetNullableText(view);
SetPlaceholder(view);
SetPlaceholderTextColor(view);
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
var view = (NullableDatePicker)Element;
if (e.PropertyName == NullableDatePicker.FontProperty.PropertyName)
SetFont(view);
else if (e.PropertyName == NullableDatePicker.XAlignProperty.PropertyName)
SetTextAlignment(view);
// else if (e.PropertyName == NullableDatePicker.HasBorderProperty.PropertyName)
// SetBorder(view);
else if (e.PropertyName == NullableDatePicker.NullableDateProperty.PropertyName)
SetNullableText(view);
else if (e.PropertyName == NullableDatePicker.PlaceholderProperty.PropertyName)
SetPlaceholder(view);
else if (e.PropertyName == NullableDatePicker.PlaceholderTextColorProperty.PropertyName)
SetPlaceholderTextColor(view);
}
/// <summary>
/// Sets the text alignment.
/// </summary>
/// <param name="view">The view.</param>
private void SetTextAlignment(NullableDatePicker view)
{
switch (view.XAlign)
{
case Xamarin.Forms.TextAlignment.Center:
Control.Gravity = GravityFlags.CenterHorizontal;
break;
case Xamarin.Forms.TextAlignment.End:
Control.Gravity = GravityFlags.End;
break;
case Xamarin.Forms.TextAlignment.Start:
Control.Gravity = GravityFlags.Start;
break;
}
}
/// <summary>
/// Sets the font.
/// </summary>
/// <param name="view">The view.</param>
private void SetFont(NullableDatePicker view)
{
if (view.Font != Font.Default)
{
Control.TextSize = view.Font.ToScaledPixel();
//Control.Typeface = view.Font.ToExtendedTypeface(Context);
}
}
/// <summary>
/// Set text based on nullable value
/// </summary>
/// <param name="view"></param>
private void SetNullableText(NullableDatePicker view)
{
if (view.NullableDate == null)
Control.Text = string.Empty;
}
/// <summary>
/// Set the placeholder
/// </summary>
/// <param name="view"></param>
private void SetPlaceholder(NullableDatePicker view)
{
Control.Hint = view.Placeholder;
}
/// <summary>
/// Sets the color of the placeholder text.
/// </summary>
/// <param name="view">The view.</param>
private void SetPlaceholderTextColor(NullableDatePicker view)
{
if (view.PlaceholderTextColor != Color.Default)
{
Control.SetHintTextColor(view.PlaceholderTextColor.ToAndroid());
}
}
}
}
using Xamarin.Forms.Platform.iOS;
using Xamarin.Forms;
using System.ComponentModel;
using UIKit;
using Foundation;
using System;
using CoreGraphics;
using NullableDateAPP.Controls;
using NullableDateAPP.iOS.Renderer;
using NullableDateAPP.iOS.Extensions;
[assembly: ExportRenderer(typeof(NullableDatePicker), typeof(NullableDatePickerRenderer))]
namespace NullableDateAPP.iOS.Renderer
{
public class NullableDatePickerRenderer : DatePickerRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<DatePicker> e)
{
base.OnElementChanged(e);
var view = Element as NullableDatePicker;
if (view != null)
{
SetFont(view);
SetTextAlignment(view);
SetBorder(view);
SetNullableText(view);
SetPlaceholderTextColor(view);
ResizeHeight();
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
var view = (NullableDatePicker)Element;
if (e.PropertyName == NullableDatePicker.FontProperty.PropertyName)
SetFont(view);
else if (e.PropertyName == NullableDatePicker.XAlignProperty.PropertyName)
SetTextAlignment(view);
else if (e.PropertyName == NullableDatePicker.HasBorderProperty.PropertyName)
SetBorder(view);
else if (e.PropertyName == NullableDatePicker.NullableDateProperty.PropertyName)
SetNullableText(view);
else if (e.PropertyName == NullableDatePicker.PlaceholderTextColorProperty.PropertyName)
SetPlaceholderTextColor(view);
ResizeHeight();
}
/// <summary>
/// Sets the text alignment.
/// </summary>
/// <param name="view">The view.</param>
private void SetTextAlignment(NullableDatePicker view)
{
switch (view.XAlign)
{
case TextAlignment.Center:
Control.TextAlignment = UITextAlignment.Center;
break;
case TextAlignment.End:
Control.TextAlignment = UITextAlignment.Right;
break;
case TextAlignment.Start:
Control.TextAlignment = UITextAlignment.Left;
break;
}
}
/// <summary>
/// Sets the font.
/// </summary>
/// <param name="view">The view.</param>
private void SetFont(NullableDatePicker view)
{
UIFont uiFont;
if (view.Font != Font.Default && (uiFont = view.Font.ToUIFont()) != null)
Control.Font = uiFont;
else if (view.Font == Font.Default)
Control.Font = UIFont.SystemFontOfSize(17f);
}
/// <summary>
/// Sets the border.
/// </summary>
/// <param name="view">The view.</param>
private void SetBorder(NullableDatePicker view)
{
Control.BorderStyle = view.HasBorder ? UITextBorderStyle.RoundedRect : UITextBorderStyle.None;
}
/// <summary>
/// Set text based on nullable value
/// </summary>
/// <param name="view"></param>
private void SetNullableText(NullableDatePicker view)
{
if (view.NullableDate == null)
Control.Text = string.Empty;
}
/// <summary>
/// Resizes the height.
/// </summary>
private void ResizeHeight()
{
if (Element.HeightRequest >= 0) return;
var height = Math.Max(Bounds.Height,
new UITextField { Font = Control.Font }.IntrinsicContentSize.Height) * 2;
Control.Frame = new CGRect(0.0f, 0.0f, (nfloat)Element.Width, (nfloat)height);
Element.HeightRequest = height;
}
/// <summary>
/// Sets the color of the placeholder text.
/// </summary>
/// <param name="view">The view.</param>
private void SetPlaceholderTextColor(NullableDatePicker view)
{
if (!string.IsNullOrEmpty(view.Placeholder))
{
var foregroundUIColor = view.PlaceholderTextColor.ToUIColor(CheckColorExtensions.SeventyPercentGrey);
var backgroundUIColor = view.BackgroundColor.ToUIColor();
var targetFont = Control.Font;
Control.AttributedPlaceholder = new NSAttributedString(view.Placeholder, targetFont, foregroundUIColor, backgroundUIColor);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment