From 8db2696131428ea3f7af8d134cfffe230b572251 Mon Sep 17 00:00:00 2001 From: Darran Jones Date: Tue, 20 Feb 2018 17:22:47 +0000 Subject: [PATCH 1/2] For iOS and Android added support for font family and font size --- Demo/MainPage.xaml | 11 +- README.md | 15 +- .../SegmentedControl.cs | 168 ++++++------ .../SegmentedControlImplementation.cs | 27 +- .../SegmentedControlImplementation.cs | 252 +++++++++--------- 5 files changed, 264 insertions(+), 209 deletions(-) diff --git a/Demo/MainPage.xaml b/Demo/MainPage.xaml index f2d8f3f..a9666af 100644 --- a/Demo/MainPage.xaml +++ b/Demo/MainPage.xaml @@ -5,10 +5,19 @@ xmlns:controls="clr-namespace:SegmentedControl.FormsPlugin.Abstractions;assembly=SegmentedControl.FormsPlugin.Abstractions" xmlns:local="clr-namespace:Demo;assembly=Demo"> + + + + + + + + + - + diff --git a/README.md b/README.md index 1377294..d237c64 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ xmlns:controls="clr-namespace:SegmentedControl.FormsPlugin.Abstractions;assembly ``` ```xml - + @@ -72,16 +72,23 @@ public void Handle_ValueChanged(object o, int e) ```SelectedSegment```: Selected segment index (int, default 0). +```FontFamily```: Font to use for text (string, default Helvetica). + +```FontSize```: Font size to use for text (float, default 15f). + +> FontFamily and FontSize supported on iOS and Android only + **Event Handlers** ```ValueChanged```: Called when a segment is selected. -#### Roadmap - -* Change font family/size #### Release Notes +2.0.2 + +[Android and iOS] Support for setting font and font size + 2.0.1 [Android] Segmented Control Not Displaying on Second Page #71 diff --git a/SegmentedControl/SegmentedControl.FormsPlugin.Abstractions/SegmentedControl.cs b/SegmentedControl/SegmentedControl.FormsPlugin.Abstractions/SegmentedControl.cs index ad83ce3..7422198 100644 --- a/SegmentedControl/SegmentedControl.FormsPlugin.Abstractions/SegmentedControl.cs +++ b/SegmentedControl/SegmentedControl.FormsPlugin.Abstractions/SegmentedControl.cs @@ -1,80 +1,98 @@ -using System; +using System; using System.Collections.Generic; using System.ComponentModel; -using Xamarin.Forms; - -namespace SegmentedControl.FormsPlugin.Abstractions -{ - /// - /// SegmentedControl Interface - /// - public class SegmentedControl : View, IViewContainer - { - public IList Children { get; set; } - - public SegmentedControl() - { - Children = new List(); - } - - public static readonly BindableProperty TintColorProperty = BindableProperty.Create("TintColor", typeof(Color), typeof(SegmentedControl), Color.Blue); - - public Color TintColor - { - get { return (Color)GetValue(TintColorProperty); } - set { SetValue(TintColorProperty, value); } - } - - public static readonly BindableProperty DisabledColorProperty = BindableProperty.Create("DisabledColor", typeof(Color), typeof(SegmentedControl), Color.Gray); - - public Color DisabledColor - { - get { return (Color)GetValue(DisabledColorProperty); } - set { SetValue(DisabledColorProperty, value); } +using Xamarin.Forms; + +namespace SegmentedControl.FormsPlugin.Abstractions +{ + /// + /// SegmentedControl Interface + /// + public class SegmentedControl : View, IViewContainer + { + public IList Children { get; set; } + + public SegmentedControl() + { + Children = new List(); + } + + public static readonly BindableProperty TintColorProperty = BindableProperty.Create("TintColor", typeof(Color), typeof(SegmentedControl), Color.Blue); + + public Color TintColor + { + get { return (Color)GetValue(TintColorProperty); } + set { SetValue(TintColorProperty, value); } + } + + public static readonly BindableProperty DisabledColorProperty = BindableProperty.Create("DisabledColor", typeof(Color), typeof(SegmentedControl), Color.Gray); + + public Color DisabledColor + { + get { return (Color)GetValue(DisabledColorProperty); } + set { SetValue(DisabledColorProperty, value); } + } + + public static readonly BindableProperty SelectedTextColorProperty = BindableProperty.Create("SelectedTextColor", typeof(Color), typeof(SegmentedControl), Color.White); + + public Color SelectedTextColor + { + get { return (Color)GetValue(SelectedTextColorProperty); } + set { SetValue(SelectedTextColorProperty, value); } + } + + public static readonly BindableProperty FontFamilyProperty = BindableProperty.Create(nameof(FontFamily), typeof(string), typeof(SegmentedControl), "Helvetica"); + + public string FontFamily + { + get { return (string)GetValue(FontFamilyProperty); } + set { SetValue(FontFamilyProperty, value); } + } + + public static readonly BindableProperty FontSizeProperty = BindableProperty.Create(nameof(FontSize), typeof(float), typeof(SegmentedControl), 15f); + + public float FontSize + { + get { return (float)GetValue(FontSizeProperty); } + set { SetValue(FontSizeProperty, value); } + } + + public static readonly BindableProperty SelectedSegmentProperty = BindableProperty.Create("SelectedSegment", typeof(int), typeof(SegmentedControl), 0); + + public int SelectedSegment + { + get + { + return (int)GetValue(SelectedSegmentProperty); + } + set + { + SetValue(SelectedSegmentProperty, value); + } } - public static readonly BindableProperty SelectedTextColorProperty = BindableProperty.Create("SelectedTextColor", typeof(Color), typeof(SegmentedControl), Color.White); - - public Color SelectedTextColor - { - get { return (Color)GetValue(SelectedTextColorProperty); } - set { SetValue(SelectedTextColorProperty, value); } - } - - public static readonly BindableProperty SelectedSegmentProperty = BindableProperty.Create("SelectedSegment", typeof(int), typeof(SegmentedControl), 0); - - public int SelectedSegment - { - get { - return (int)GetValue(SelectedSegmentProperty); - } - set { - SetValue(SelectedSegmentProperty, value); - } - } - - public event EventHandler ValueChanged; - - [EditorBrowsable(EditorBrowsableState.Never)] - public void SendValueChanged() - { + public event EventHandler ValueChanged; + + [EditorBrowsable(EditorBrowsableState.Never)] + public void SendValueChanged() + { ValueChanged?.Invoke(this, new ValueChangedEventArgs { NewValue = this.SelectedSegment }); - } - } - - public class SegmentedControlOption : View - { - public static readonly BindableProperty TextProperty = BindableProperty.Create("Text", typeof(string), typeof(SegmentedControlOption), string.Empty); - - public string Text - { - get { return (string)GetValue(TextProperty); } - set { SetValue(TextProperty, value); } - } - } - - public class ValueChangedEventArgs : EventArgs - { - public int NewValue { get; set; } - } -} + } + } + + public class SegmentedControlOption : View + { + public static readonly BindableProperty TextProperty = BindableProperty.Create("Text", typeof(string), typeof(SegmentedControlOption), string.Empty); + + public string Text + { + get { return (string)GetValue(TextProperty); } + set { SetValue(TextProperty, value); } + } + } + + public class ValueChangedEventArgs : EventArgs + { + public int NewValue { get; set; } + } +} diff --git a/SegmentedControl/SegmentedControl.FormsPlugin.Android/SegmentedControlImplementation.cs b/SegmentedControl/SegmentedControl.FormsPlugin.Android/SegmentedControlImplementation.cs index ae60f9c..572fa65 100644 --- a/SegmentedControl/SegmentedControl.FormsPlugin.Android/SegmentedControlImplementation.cs +++ b/SegmentedControl/SegmentedControl.FormsPlugin.Android/SegmentedControlImplementation.cs @@ -6,6 +6,8 @@ using Android.Views; using Android.Graphics.Drawables; using Android.Content; +using Android.Graphics; +using Android.Util; [assembly: ExportRenderer(typeof(SegmentedControl.FormsPlugin.Abstractions.SegmentedControl), typeof(SegmentedControlRenderer))] namespace SegmentedControl.FormsPlugin.Android @@ -92,7 +94,7 @@ protected override void OnElementPropertyChanged(object sender, System.Component case "Renderer": Element?.SendValueChanged(); break; - case "SelectedSegment": + case nameof(Element.SelectedSegment): var option = (RadioButton)nativeControl.GetChildAt(Element.SelectedSegment); if (option != null) @@ -129,13 +131,13 @@ protected override void OnElementPropertyChanged(object sender, System.Component Element.SendValueChanged(); break; - case "TintColor": + case nameof(Element.TintColor): + case nameof(Element.IsEnabled): + case nameof(Element.FontFamily): + case nameof(Element.FontSize): OnPropertyChanged(); - break; - case "IsEnabled": - OnPropertyChanged(); - break; - case "SelectedTextColor": + break; + case nameof(Element.SelectedTextColor): var v = (RadioButton)nativeControl.GetChildAt(Element.SelectedSegment); v.SetTextColor(Element.SelectedTextColor.ToAndroid()); break; @@ -185,7 +187,11 @@ void ConfigureRadioButton(int i, RadioButton rb) selectedShape.SetColor(color); unselectedShape.SetStroke(3, color); - rb.Enabled = Element.IsEnabled; + rb.Enabled = Element.IsEnabled; + + var font = Font.OfSize(Element.FontFamily, Element.FontSize); + rb.SetTypeface(font.ToTypeface(), TypefaceStyle.Normal); + rb.SetTextSize(ComplexUnitType.Sp, font.ToScaledPixel()); } void NativeControl_ValueChanged(object sender, RadioGroup.CheckedChangeEventArgs e) @@ -222,8 +228,8 @@ protected override void Dispose(bool disposing) { base.Dispose(disposing); } - catch (Exception ex) - { + catch + { return; } } @@ -234,4 +240,5 @@ public static void Init() { var temp = DateTime.Now; } } + } \ No newline at end of file diff --git a/SegmentedControl/SegmentedControl.FormsPlugin.iOS/SegmentedControlImplementation.cs b/SegmentedControl/SegmentedControl.FormsPlugin.iOS/SegmentedControlImplementation.cs index ef0f776..55b6fe7 100644 --- a/SegmentedControl/SegmentedControl.FormsPlugin.iOS/SegmentedControlImplementation.cs +++ b/SegmentedControl/SegmentedControl.FormsPlugin.iOS/SegmentedControlImplementation.cs @@ -1,127 +1,141 @@ -using System; -using Xamarin.Forms; -using SegmentedControl.FormsPlugin.iOS; -using Xamarin.Forms.Platform.iOS; +using System; +using Xamarin.Forms; +using SegmentedControl.FormsPlugin.iOS; +using Xamarin.Forms.Platform.iOS; using UIKit; -[assembly: ExportRenderer(typeof(SegmentedControl.FormsPlugin.Abstractions.SegmentedControl), typeof(SegmentedControlRenderer))] -namespace SegmentedControl.FormsPlugin.iOS +[assembly: ExportRenderer(typeof(SegmentedControl.FormsPlugin.Abstractions.SegmentedControl), typeof(SegmentedControlRenderer))] +namespace SegmentedControl.FormsPlugin.iOS { - /// - /// SegmentedControl Renderer - /// - public class SegmentedControlRenderer : ViewRenderer - { - UISegmentedControl nativeControl; - - protected override void OnElementChanged(ElementChangedEventArgs e) - { - base.OnElementChanged(e); - - if (Control == null) - { - // Instantiate the native control and assign it to the Control property with - // the SetNativeControl method - - nativeControl = new UISegmentedControl(); - - for (var i = 0; i + /// SegmentedControl Renderer + /// + public class SegmentedControlRenderer : ViewRenderer + { + UISegmentedControl nativeControl; + + protected override void OnElementChanged(ElementChangedEventArgs e) + { + base.OnElementChanged(e); + + if (Control == null) + { + // Instantiate the native control and assign it to the Control property with + // the SetNativeControl method + + nativeControl = new UISegmentedControl(); + + for (var i = 0; i < Element.Children.Count; i++) + { + nativeControl.InsertSegment(Element.Children[i].Text, i, false); + } + + nativeControl.Enabled = Element.IsEnabled; + nativeControl.TintColor = Element.IsEnabled ? Element.TintColor.ToUIColor() : Element.DisabledColor.ToUIColor(); + SetSelectedTextColor(); + SetFont(); + + nativeControl.SelectedSegment = Element.SelectedSegment; + + SetNativeControl(nativeControl); + } + + if (e.OldElement != null) + { + // Unsubscribe from event handlers and cleanup any resources + + if (nativeControl != null) + nativeControl.ValueChanged -= NativeControl_ValueChanged; + } + + if (e.NewElement != null) + { + // Configure the control and subscribe to event handlers + + nativeControl.ValueChanged += NativeControl_ValueChanged; + } + } + + protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) + { + base.OnElementPropertyChanged(sender, e); + if (nativeControl == null || Element == null) return; - switch (e.PropertyName) - { - case "Renderer": - Element?.SendValueChanged(); - break; - case "SelectedSegment": + switch (e.PropertyName) + { + case "Renderer": + Element?.SendValueChanged(); + break; + case nameof(Element.SelectedSegment): nativeControl.SelectedSegment = Element.SelectedSegment; - Element.SendValueChanged(); - break; - case "TintColor": - nativeControl.TintColor = Element.IsEnabled ? Element.TintColor.ToUIColor() : Element.DisabledColor.ToUIColor(); - break; - case "IsEnabled": + Element.SendValueChanged(); + break; + case nameof(Element.TintColor): + nativeControl.TintColor = Element.IsEnabled ? Element.TintColor.ToUIColor() : Element.DisabledColor.ToUIColor(); + break; + case nameof(Element.IsEnabled): nativeControl.Enabled = Element.IsEnabled; nativeControl.TintColor = Element.IsEnabled ? Element.TintColor.ToUIColor() : Element.DisabledColor.ToUIColor(); - break; - case "SelectedTextColor": - SetSelectedTextColor(); - break; - - } - - } - - void SetSelectedTextColor() - { - var attr = new UITextAttributes(); - attr.TextColor = Element.SelectedTextColor.ToUIColor(); - nativeControl.SetTitleTextAttributes(attr, UIControlState.Selected); - } - - void NativeControl_ValueChanged (object sender, EventArgs e) - { - Element.SelectedSegment = (int)nativeControl.SelectedSegment; - } - - protected override void Dispose(bool disposing) - { - if (nativeControl != null) - { - nativeControl.ValueChanged -= NativeControl_ValueChanged; - nativeControl.Dispose(); - nativeControl = null; - } - - try - { - base.Dispose(disposing); - } - catch (Exception ex) - { - return; - } - } - - /// - /// Used for registration with dependency service - /// - public static void Init() - { - var temp = DateTime.Now; - } - } -} + break; + case nameof(Element.SelectedTextColor): + SetSelectedTextColor(); + break; + case nameof(Element.FontFamily): + case nameof(Element.FontSize): + SetFont(); + break; + } + + } + + void SetSelectedTextColor() + { + var attr = new UITextAttributes + { + TextColor = Element.SelectedTextColor.ToUIColor() + }; + nativeControl.SetTitleTextAttributes(attr, UIControlState.Selected); + } + + void SetFont() + { + var font = UIFont.FromName(Element.FontFamily, Element.FontSize); + + if (font != null) // Attempting to set the font to null causes a crash + nativeControl.SetTitleTextAttributes(new UITextAttributes { Font = font }, UIControlState.Normal); + } + + void NativeControl_ValueChanged(object sender, EventArgs e) + { + Element.SelectedSegment = (int)nativeControl.SelectedSegment; + } + + protected override void Dispose(bool disposing) + { + if (nativeControl != null) + { + nativeControl.ValueChanged -= NativeControl_ValueChanged; + nativeControl.Dispose(); + nativeControl = null; + } + + try + { + base.Dispose(disposing); + } + catch + { + return; + } + } + + /// + /// Used for registration with dependency service + /// + public static void Init() + { + var temp = DateTime.Now; + } + } +} From 12cfbac17f98312ddeb8d940963a842e312113e2 Mon Sep 17 00:00:00 2001 From: Darran Date: Tue, 13 Mar 2018 15:37:55 +0000 Subject: [PATCH 2/2] Updated readme.md Fixed broken example for ValueChanged event handler --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d237c64..427968f 100644 --- a/README.md +++ b/README.md @@ -42,11 +42,11 @@ xmlns:controls="clr-namespace:SegmentedControl.FormsPlugin.Abstractions;assembly #### Event handler ``` -public void Handle_ValueChanged(object o, int e) +public void Handle_ValueChanged(object o, SegmentedControl.FormsPlugin.Abstractions.ValueChangedEventArgs e) { SegContent.Children.Clear(); - switch (e) + switch (e.NewValue) { case 0: SegContent.Children.Add(new Label() { Text="Tab 1 selected" });