Skip to content

Instantly share code, notes, and snippets.

@dylanberry
Last active December 1, 2018 21:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dylanberry/d4364abab0915fd9e0ca6abe4aabadc0 to your computer and use it in GitHub Desktop.
Save dylanberry/d4364abab0915fd9e0ca6abe4aabadc0 to your computer and use it in GitHub Desktop.
/// <summary>
/// The check box.
/// </summary>
public class CheckBox : View
{
/// <summary>
/// The checked state property.
/// </summary>
public static readonly BindableProperty CheckedProperty =
BindableProperty.Create(nameof(Checked), typeof (bool), typeof (CheckBox), false, BindingMode.TwoWay,
propertyChanged: OnCheckedPropertyChanged);
/// <summary>
/// The checked text property.
/// </summary>
public static readonly BindableProperty CheckedTextProperty =
BindableProperty.Create(nameof(CheckedText), typeof(string), typeof(CheckBox), string.Empty, BindingMode.TwoWay);
/// <summary>
/// The unchecked text property.
/// </summary>
public static readonly BindableProperty UncheckedTextProperty =
BindableProperty.Create(nameof(UncheckedText), typeof (string), typeof (CheckBox), string.Empty, BindingMode.TwoWay);
/// <summary>
/// The default text property.
/// </summary>
public static readonly BindableProperty DefaultTextProperty =
BindableProperty.Create(nameof(Text), typeof (string), typeof (CheckBox), string.Empty);
/// <summary>
/// Identifies the TextColor bindable property.
/// </summary>
///
/// <remarks/>
public static readonly BindableProperty TextColorProperty =
BindableProperty.Create(nameof(TextColor), typeof(Color), typeof(CheckBox), Color.Default);
/// <summary>
/// The font size property
/// </summary>
public static readonly BindableProperty FontSizeProperty =
BindableProperty.Create(nameof(FontSize), typeof(double), typeof(CheckBox), double.MinValue);
/// <summary>
/// The font name property.
/// </summary>
public static readonly BindableProperty FontNameProperty =
BindableProperty.Create(nameof(FontName), typeof (string), typeof (CheckBox), string.Empty);
/// <summary>
/// The checked changed event.
/// </summary>
public event EventHandler<CheckedItemEventArgs> CheckedChanged;
/// <summary>
/// Gets or sets a value indicating whether the control is checked.
/// </summary>
/// <value>The checked state.</value>
public bool Checked
{
get => (bool) GetValue(CheckedProperty);
set
{
if (Checked != value)
{
SetValue(CheckedProperty, value);
CheckedChanged?.Invoke(this, new CheckedItemEventArgs {Checked = value, BoundObject = Parent?.BindingContext});
}
}
}
/// <summary>
/// Gets or sets a value indicating the checked text.
/// </summary>
/// <value>The checked state.</value>
/// <remarks>
/// Overwrites the default text property if set when checkbox is checked.
/// </remarks>
public string CheckedText
{
get => (string)GetValue(CheckedTextProperty);
set => SetValue(CheckedTextProperty, value);
}
/// <summary>
/// Gets or sets a value indicating whether the control is checked.
/// </summary>
/// <value>The checked state.</value>
/// <remarks>
/// Overwrites the default text property if set when checkbox is checked.
/// </remarks>
public string UncheckedText
{
get => (string)GetValue(UncheckedTextProperty);
set => SetValue(UncheckedTextProperty, value);
}
/// <summary>
/// Gets or sets the text.
/// </summary>
public string DefaultText
{
get => (string)GetValue(DefaultTextProperty);
set => SetValue(DefaultTextProperty, value);
}
/// <summary>
/// Gets or sets the color of the text.
/// </summary>
/// <value>The color of the text.</value>
public Color TextColor
{
get => (Color)GetValue(TextColorProperty);
set => SetValue(TextColorProperty, value);
}
/// <summary>
/// Gets or sets the size of the font.
/// </summary>
/// <value>The size of the font.</value>
public double FontSize
{
get => (double)GetValue(FontSizeProperty);
set => SetValue(FontSizeProperty, value);
}
/// <summary>
/// Gets or sets the name of the font.
/// </summary>
/// <value>The name of the font.</value>
public string FontName
{
get => (string)GetValue(FontNameProperty);
set => SetValue(FontNameProperty, value);
}
/// <summary>
/// Gets the text.
/// </summary>
/// <value>The text.</value>
public string Text => Checked
? (string.IsNullOrEmpty(CheckedText) ? DefaultText : CheckedText)
: (string.IsNullOrEmpty(UncheckedText) ? DefaultText : UncheckedText);
/// <summary>
/// Called when [checked property changed].
/// </summary>
/// <param name="bindable">The bindable.</param>
/// <param name="oldvalue">if set to <c>true</c> [oldvalue].</param>
/// <param name="newvalue">if set to <c>true</c> [newvalue].</param>
private static void OnCheckedPropertyChanged(BindableObject bindable, object oldvalue, object newvalue)
{
var checkBox = (CheckBox)bindable;
checkBox.Checked = (bool) newvalue;
}
}
public class CheckedItemEventArgs : EventArgs
{
public object BoundObject { get; set; }
public bool Checked { get; set; }
}
/// <summary>
/// Class CheckBoxRenderer.
/// </summary>
public class CheckBoxRenderer : Xamarin.Forms.Platform.Android.AppCompat.ViewRenderer<GGC.Mobile.Controls.CheckBox, Android.Widget.CheckBox>
{
private ColorStateList defaultTextColor;
/// <summary>
/// Called when [element changed].
/// </summary>
/// <param name="e">The e.</param>
protected override void OnElementChanged(ElementChangedEventArgs<Controls.CheckBox> e)
{
base.OnElementChanged(e);
if (this.Control == null)
{
var checkBox = new Android.Widget.CheckBox(this.Context);
checkBox.CheckedChange += CheckBoxCheckedChange;
defaultTextColor = checkBox.TextColors;
this.SetNativeControl(checkBox);
}
Control.Text = e.NewElement.Text;
Control.Checked = e.NewElement.Checked;
UpdateTextColor();
if (e.NewElement.FontSize > 0)
{
Control.TextSize = (float)e.NewElement.FontSize;
}
if (!string.IsNullOrEmpty(e.NewElement.FontName))
{
Control.Typeface = TrySetFont(e.NewElement.FontName);
}
}
/// <summary>
/// Handles the <see cref="E:ElementPropertyChanged" /> event.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="PropertyChangedEventArgs"/> instance containing the event data.</param>
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
switch (e.PropertyName)
{
case "Checked":
Control.Text = Element.Text;
Control.Checked = Element.Checked;
break;
case "TextColor":
UpdateTextColor();
break;
case "FontName":
if (!string.IsNullOrEmpty(Element.FontName))
{
Control.Typeface = TrySetFont(Element.FontName);
}
break;
case "FontSize":
if (Element.FontSize > 0)
{
Control.TextSize = (float)Element.FontSize;
}
break;
case "CheckedText":
case "UncheckedText":
Control.Text = Element.Text;
break;
default:
System.Diagnostics.Debug.WriteLine("Property change for {0} has not been implemented.", e.PropertyName);
break;
}
}
/// <summary>
/// CheckBoxes the checked change.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="Android.Widget.CompoundButton.CheckedChangeEventArgs"/> instance containing the event data.</param>
void CheckBoxCheckedChange(object sender, Android.Widget.CompoundButton.CheckedChangeEventArgs e)
{
this.Element.Checked = e.IsChecked;
}
/// <summary>
/// Tries the set font.
/// </summary>
/// <param name="fontName">Name of the font.</param>
/// <returns>Typeface.</returns>
private Typeface TrySetFont(string fontName)
{
Typeface tf = Typeface.Default;
try
{
tf = Typeface.CreateFromAsset(Context.Assets, fontName);
return tf;
}
catch (Exception ex)
{
Console.Write("not found in assets {0}", ex);
try
{
tf = Typeface.CreateFromFile(fontName);
return tf;
}
catch (Exception ex1)
{
Console.Write(ex1);
return Typeface.Default;
}
}
}
/// <summary>
/// Updates the color of the text
/// </summary>
private void UpdateTextColor()
{
if (Control == null || Element == null)
return;
if (Element.TextColor == Xamarin.Forms.Color.Default)
Control.SetTextColor(defaultTextColor);
else
Control.SetTextColor(Element.TextColor.ToAndroid());
}
protected override CheckBox CreateNativeControl()
{
throw new NotImplementedException();
}
}
/// <summary>
/// The check box renderer for iOS.
/// </summary>
public class CheckBoxRenderer : ViewRenderer<CheckBox, CheckBoxView>
{
private UIColor defaultTextColor;
/// <summary>
/// Handles the Element Changed event
/// </summary>
/// <param name="e">The e.</param>
protected override void OnElementChanged(ElementChangedEventArgs<CheckBox> e)
{
base.OnElementChanged(e);
if (Element == null) return;
BackgroundColor = Element.BackgroundColor.ToUIColor();
if (e.NewElement != null)
{
if (Control == null)
{
var checkBox = new CheckBoxView(Bounds);
checkBox.TouchUpInside += (s, args) => Element.Checked = Control.Checked;
defaultTextColor = checkBox.TitleColor(UIControlState.Normal);
SetNativeControl(checkBox);
}
Control.LineBreakMode = UILineBreakMode.CharacterWrap;
Control.VerticalAlignment = UIControlContentVerticalAlignment.Top;
Control.CheckedTitle = string.IsNullOrEmpty(e.NewElement.CheckedText) ? e.NewElement.DefaultText : e.NewElement.CheckedText;
Control.UncheckedTitle = string.IsNullOrEmpty(e.NewElement.UncheckedText) ? e.NewElement.DefaultText : e.NewElement.UncheckedText;
Control.Checked = e.NewElement.Checked;
Control.Alpha = new nfloat(Control.Enabled ? 1.0f : 0.6f);
Control.UserInteractionEnabled = Control.Enabled;
Control.Enabled = true;
UpdateTextColor();
}
Control.Frame = Frame;
Control.Bounds = Bounds;
UpdateFont();
}
/// <summary>
/// Resizes the text.
/// </summary>
private void ResizeText()
{
if (Element == null)
return;
var text = Element.Checked ? string.IsNullOrEmpty(Element.CheckedText) ? Element.DefaultText : Element.CheckedText :
string.IsNullOrEmpty(Element.UncheckedText) ? Element.DefaultText : Element.UncheckedText;
var bounds = Control.Bounds;
var width = Control.TitleLabel.Bounds.Width;
var height = text.StringHeight(Control.Font, width);
var minHeight = string.Empty.StringHeight(Control.Font, width);
var requiredLines = Math.Round(height / minHeight, MidpointRounding.AwayFromZero);
var supportedLines = Math.Round(bounds.Height / minHeight, MidpointRounding.ToEven);
if (supportedLines != requiredLines)
{
bounds.Height += (float)(minHeight * (requiredLines - supportedLines));
Control.Bounds = bounds;
Element.HeightRequest = bounds.Height;
}
}
/// <summary>
/// Draws the specified rect.
/// </summary>
/// <param name="rect">The rect.</param>
public override void Draw(CoreGraphics.CGRect rect)
{
base.Draw(rect);
ResizeText();
}
/// <summary>
/// Updates the font.
/// </summary>
private void UpdateFont()
{
if (!string.IsNullOrEmpty(Element.FontName))
{
var font = UIFont.FromName(Element.FontName, (Element.FontSize > 0) ? (float)Element.FontSize : 12.0f);
if (font != null)
{
Control.Font = font;
}
}
else if (Element.FontSize > 0)
{
var font = UIFont.FromName(Control.Font.Name, (float)Element.FontSize);
if (font != null)
{
Control.Font = font;
}
}
}
private void UpdateTextColor()
{
Control.SetTitleColor(Element.TextColor.ToUIColor(defaultTextColor), UIControlState.Normal);
Control.SetTitleColor(Element.TextColor.ToUIColor(defaultTextColor), UIControlState.Selected);
}
/// <summary>
/// Handles the <see cref="E:ElementPropertyChanged" /> event.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="PropertyChangedEventArgs"/> instance containing the event data.</param>
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
switch (e.PropertyName)
{
case "Checked":
Control.Checked = Element.Checked;
break;
case "TextColor":
UpdateTextColor();
break;
case "CheckedText":
Control.CheckedTitle = string.IsNullOrEmpty(Element.CheckedText) ? Element.DefaultText : Element.CheckedText;
break;
case "UncheckedText":
Control.UncheckedTitle = string.IsNullOrEmpty(Element.UncheckedText) ? Element.DefaultText : Element.UncheckedText;
break;
case "FontSize":
UpdateFont();
break;
case "FontName":
UpdateFont();
break;
case "Element":
break;
default:
System.Diagnostics.Debug.WriteLine("Property change for {0} has not been implemented.", e.PropertyName);
return;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment