From 26a9f00c0e3dbfa783a65110665e566a21aa562a Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Fri, 15 Jan 2021 04:58:05 -0600 Subject: [PATCH] Shapes on iOS fail to render if the bounds of the view is set prior to renderer creation (#13284) fixes #12245 fixes #13225 fixes #12911 fixes #13096 fixes #13164 fixes #11924 fixes #11656 fixes #12844 fixes #12521 fixes #13407 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * UI Test * Render Shape if it has an initial size already set * - fix ui tests * Unified issues with the same fix. Co-authored-by: Javier Suárez Ruiz --- .../Issue11924.cs | 87 ++++++++++++++ .../Issue12521.xaml | 78 ++++++++++++ .../Issue12521.xaml.cs | 37 ++++++ .../Issue12911.xaml | 113 ++++++++++++++++++ .../Issue12911.xaml.cs | 32 +++++ .../Issue13164.cs | 105 ++++++++++++++++ .../TestPages/TestPages.cs | 28 +++++ ...rin.Forms.Controls.Issues.Shared.projitems | 10 ++ .../Shapes/EllipseRenderer.cs | 2 +- .../Shapes/LineRenderer.cs | 2 +- .../Shapes/PathRenderer.cs | 2 +- .../Shapes/PolygonRenderer.cs | 2 +- .../Shapes/PolylineRenderer.cs | 2 +- .../Shapes/RectangleRenderer.cs | 2 +- .../Shapes/ShapeRenderer.cs | 7 ++ .../AssertionExtensions.cs | 56 +++++++++ .../ShapeTests.cs | 37 ++++++ ...amarin.Forms.Platform.iOS.UnitTests.csproj | 1 + .../Shapes/EllipseRenderer.cs | 2 +- .../Shapes/LineRenderer.cs | 2 +- .../Shapes/PathRenderer.cs | 2 +- .../Shapes/PolygonRenderer.cs | 2 +- .../Shapes/PolylineRenderer.cs | 2 +- .../Shapes/RectangleRenderer.cs | 2 +- .../Shapes/ShapeRenderer.cs | 7 ++ 25 files changed, 610 insertions(+), 12 deletions(-) create mode 100644 Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue11924.cs create mode 100644 Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue12521.xaml create mode 100644 Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue12521.xaml.cs create mode 100644 Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue12911.xaml create mode 100644 Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue12911.xaml.cs create mode 100644 Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue13164.cs create mode 100644 Xamarin.Forms.Platform.iOS.UnitTests/ShapeTests.cs diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue11924.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue11924.cs new file mode 100644 index 000000000..f62882494 --- /dev/null +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue11924.cs @@ -0,0 +1,87 @@ +using Xamarin.Forms.CustomAttributes; +using Xamarin.Forms.Internals; +using Xamarin.Forms.Shapes; +using System.Collections.Generic; + +#if UITEST +using Xamarin.Forms.Core.UITests; +using Xamarin.UITest; +using NUnit.Framework; +#endif + +namespace Xamarin.Forms.Controls.Issues +{ +#if UITEST + [Category(UITestCategories.Shape)] +#endif + [Preserve(AllMembers = true)] + [Issue(IssueTracker.Github, 11924, "[Bug] Shapes not loading in Xamarin ShellContent Tab once it is navigated back from other Tab", + PlatformAffected.All)] + public class Issue11924 : TestShell + { + const string Test1 = "Test 1"; + const string Test2 = "Test 2"; + + public Issue11924() + { + + } + + protected override void Init() + { + AddBottomTab(CreatePage1(Test1), Test1); + AddBottomTab(CreatePage2(Test2), Test2); + + static ContentPage CreatePage1(string title) + { + var layout = new StackLayout(); + + var instructions = new Label + { + Padding = 12, + BackgroundColor = Color.Black, + TextColor = Color.White, + Text = "Navigate to the second Tab" + }; + + var ellipse = new Ellipse + { + HorizontalOptions = LayoutOptions.Start, + HeightRequest = 50, + WidthRequest = 100, + Fill = Brush.Red + }; + + layout.Children.Add(instructions); + layout.Children.Add(ellipse); + + return new ContentPage + { + Title = title, + Content = layout + }; + } + + static ContentPage CreatePage2(string title) + { + var layout = new StackLayout(); + + var instructions = new Label + { + Padding = 12, + BackgroundColor = Color.Black, + TextColor = Color.White, + Text = "Navigate back to the first tab, and verify if the Ellipse is rendering or not." + }; + + layout.Children.Add(instructions); + + return new ContentPage + { + Title = title, + Content = layout + }; + } + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue12521.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue12521.xaml new file mode 100644 index 000000000..8690a4408 --- /dev/null +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue12521.xaml @@ -0,0 +1,78 @@ + + + + + \ No newline at end of file diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue12521.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue12521.xaml.cs new file mode 100644 index 000000000..6bf40b9ab --- /dev/null +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue12521.xaml.cs @@ -0,0 +1,37 @@ +using Xamarin.Forms.CustomAttributes; +using Xamarin.Forms.Internals; +using Xamarin.Forms.Xaml; + +#if UITEST +using Xamarin.UITest; +using Xamarin.UITest.Queries; +using NUnit.Framework; +using Xamarin.Forms.Core.UITests; +#endif + +namespace Xamarin.Forms.Controls.Issues +{ +#if UITEST + [Category(UITestCategories.Shape)] +#endif +#if APP + [XamlCompilation(XamlCompilationOptions.Compile)] +#endif + [Preserve(AllMembers = true)] + [Issue(IssueTracker.Github, 12521, "[Bug][iOS] Shapes disappear in a Frame in a ListView when scrolled", + PlatformAffected.iOS)] + public partial class Issue12521 : TestContentPage + { + public Issue12521() + { +#if APP + InitializeComponent(); +#endif + } + + protected override void Init() + { + + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue12911.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue12911.xaml new file mode 100644 index 000000000..1591f5ff5 --- /dev/null +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue12911.xaml @@ -0,0 +1,113 @@ + + + + + + + \ No newline at end of file diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue12911.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue12911.xaml.cs new file mode 100644 index 000000000..b64ef618d --- /dev/null +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue12911.xaml.cs @@ -0,0 +1,32 @@ +using Xamarin.Forms.CustomAttributes; +using Xamarin.Forms.Internals; + +#if UITEST +using Xamarin.Forms.Core.UITests; +using Xamarin.UITest; +using NUnit.Framework; +#endif + +namespace Xamarin.Forms.Controls.Issues +{ + [Preserve(AllMembers = true)] + [Issue(IssueTracker.Github, 12911, "[Bug] Shapes in SwipeView of a CollectionView/ListView has several issues", + PlatformAffected.Android | PlatformAffected.iOS)] +#if UITEST + [NUnit.Framework.Category(UITestCategories.Brush)] +#endif + public partial class Issue12911 : TestContentPage + { + public Issue12911() + { +#if APP + InitializeComponent(); +#endif + } + + protected override void Init() + { + + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue13164.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue13164.cs new file mode 100644 index 000000000..3ed0b667d --- /dev/null +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue13164.cs @@ -0,0 +1,105 @@ +using Xamarin.Forms.CustomAttributes; +using Xamarin.Forms.Internals; +using Xamarin.Forms.Shapes; + +#if UITEST +using Xamarin.Forms.Core.UITests; +using Xamarin.UITest; +using NUnit.Framework; +#endif + +namespace Xamarin.Forms.Controls.Issues +{ +#if UITEST + [Category(UITestCategories.Shape)] +#endif + [Preserve(AllMembers = true)] + [Issue(IssueTracker.Github, 13164, "[Bug] Shapes broken in Xamarin if used within NavigationPage once and navigated back", + PlatformAffected.Android | PlatformAffected.iOS)] + public class Issue13164 : TestContentPage + { + Issue13164SecondPage _issue13164SecondPage; + + public Issue13164() + { + } + + protected override void Init() + { + Title = "Issue 13164"; + + var layout = new StackLayout(); + + var instructions = new Label + { + Padding = 12, + BackgroundColor = Color.Black, + TextColor = Color.White, + Text = "Tap the Button to navigate to the details page with some Shapes." + }; + + var navigateButton = new Button + { + Text = "Navigate" + }; + + layout.Children.Add(instructions); + layout.Children.Add(navigateButton); + + Content = layout; + + navigateButton.Clicked += (sender, args) => + { + if (_issue13164SecondPage == null) + { + _issue13164SecondPage = new Issue13164SecondPage(); + } + + var navPage = new NavigationPage(_issue13164SecondPage); + Navigation.PushAsync(navPage); + }; + } + } + + [Preserve(AllMembers = true)] + public class Issue13164SecondPage : ContentPage + { + public Issue13164SecondPage() + { + var layout = new StackLayout(); + + var instructions = new Label + { + Padding = 12, + BackgroundColor = Color.Black, + TextColor = Color.White, + Text = "Navigate back, and navigate again to this page several times. If shapes are always rendered, the test has passed." + }; + + var ellipse = new Ellipse + { + HorizontalOptions = LayoutOptions.Start, + Stroke = Brush.DarkBlue, + Fill = Brush.BlueViolet, + HeightRequest = 50, + WidthRequest = 100 + }; + + var rectangle = new Shapes.Rectangle + { + HorizontalOptions = LayoutOptions.Start, + StrokeThickness = 3, + Stroke = Brush.DarkOliveGreen, + Fill = Brush.Orange, + HeightRequest = 80, + WidthRequest = 120 + }; + + layout.Children.Add(instructions); + layout.Children.Add(ellipse); + layout.Children.Add(rectangle); + + Content = layout; + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/TestPages/TestPages.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/TestPages/TestPages.cs index 3e5fbd774..ca8b67480 100644 --- a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/TestPages/TestPages.cs +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/TestPages/TestPages.cs @@ -658,6 +658,34 @@ namespace Xamarin.Forms.Controls content.Route = content.Title; } + public ContentPage AddBottomTab(ContentPage page, string title, string icon = null) + { + if (Items.Count == 0) + { + var item = AddContentPage(page); + item.Items[0].Items[0].Title = title ?? page.Title; + item.Items[0].Title = title ?? page.Title; + return page; + } + + Items[0].Items.Add(new ShellSection() + { + AutomationId = title, + Route = title, + Title = title, + Icon = icon, + Items = + { + new ShellContent() + { + ContentTemplate = new DataTemplate(() => page), + Title = title + } + } + }); + return page; + } + public ContentPage AddBottomTab(string title, string icon = null) { ContentPage page = new ContentPage(); diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems index e4554d5df..9f150b4dc 100644 --- a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems @@ -1696,6 +1696,10 @@ + + + + @@ -2086,6 +2090,12 @@ MSBuild:UpdateDesignTimeXaml + + MSBuild:UpdateDesignTimeXaml + + + MSBuild:UpdateDesignTimeXaml + diff --git a/Xamarin.Forms.Platform.Android/Shapes/EllipseRenderer.cs b/Xamarin.Forms.Platform.Android/Shapes/EllipseRenderer.cs index cb3153806..339cebceb 100644 --- a/Xamarin.Forms.Platform.Android/Shapes/EllipseRenderer.cs +++ b/Xamarin.Forms.Platform.Android/Shapes/EllipseRenderer.cs @@ -13,7 +13,7 @@ namespace Xamarin.Forms.Platform.Android protected override void OnElementChanged(ElementChangedEventArgs args) { - if (Control == null) + if (Control == null && args.NewElement != null) { SetNativeControl(new EllipseView(Context)); } diff --git a/Xamarin.Forms.Platform.Android/Shapes/LineRenderer.cs b/Xamarin.Forms.Platform.Android/Shapes/LineRenderer.cs index 0ef8779d3..25bd21ea9 100644 --- a/Xamarin.Forms.Platform.Android/Shapes/LineRenderer.cs +++ b/Xamarin.Forms.Platform.Android/Shapes/LineRenderer.cs @@ -14,7 +14,7 @@ namespace Xamarin.Forms.Platform.Android protected override void OnElementChanged(ElementChangedEventArgs args) { - if (Control == null) + if (Control == null && args.NewElement != null) { SetNativeControl(new LineView(Context)); } diff --git a/Xamarin.Forms.Platform.Android/Shapes/PathRenderer.cs b/Xamarin.Forms.Platform.Android/Shapes/PathRenderer.cs index 3179b10dc..b17865b9a 100644 --- a/Xamarin.Forms.Platform.Android/Shapes/PathRenderer.cs +++ b/Xamarin.Forms.Platform.Android/Shapes/PathRenderer.cs @@ -15,7 +15,7 @@ namespace Xamarin.Forms.Platform.Android protected override void OnElementChanged(ElementChangedEventArgs args) { - if (Control == null) + if (Control == null && args.NewElement != null) { SetNativeControl(new PathView(Context)); } diff --git a/Xamarin.Forms.Platform.Android/Shapes/PolygonRenderer.cs b/Xamarin.Forms.Platform.Android/Shapes/PolygonRenderer.cs index db465039a..5d26d35ad 100644 --- a/Xamarin.Forms.Platform.Android/Shapes/PolygonRenderer.cs +++ b/Xamarin.Forms.Platform.Android/Shapes/PolygonRenderer.cs @@ -18,7 +18,7 @@ namespace Xamarin.Forms.Platform.Android protected override void OnElementChanged(ElementChangedEventArgs args) { - if (Control == null) + if (Control == null && args.NewElement != null) { SetNativeControl(new PolygonView(Context)); } diff --git a/Xamarin.Forms.Platform.Android/Shapes/PolylineRenderer.cs b/Xamarin.Forms.Platform.Android/Shapes/PolylineRenderer.cs index 0fce6eafc..20a48a660 100644 --- a/Xamarin.Forms.Platform.Android/Shapes/PolylineRenderer.cs +++ b/Xamarin.Forms.Platform.Android/Shapes/PolylineRenderer.cs @@ -18,7 +18,7 @@ namespace Xamarin.Forms.Platform.Android protected override void OnElementChanged(ElementChangedEventArgs args) { - if (Control == null) + if (Control == null && args.NewElement != null) { SetNativeControl(new PolylineView(Context)); } diff --git a/Xamarin.Forms.Platform.Android/Shapes/RectangleRenderer.cs b/Xamarin.Forms.Platform.Android/Shapes/RectangleRenderer.cs index c6623d22c..09b70f9a1 100644 --- a/Xamarin.Forms.Platform.Android/Shapes/RectangleRenderer.cs +++ b/Xamarin.Forms.Platform.Android/Shapes/RectangleRenderer.cs @@ -15,7 +15,7 @@ namespace Xamarin.Forms.Platform.Android protected override void OnElementChanged(ElementChangedEventArgs args) { - if (Control == null) + if (Control == null && args.NewElement != null) { SetNativeControl(new RectView(Context)); } diff --git a/Xamarin.Forms.Platform.Android/Shapes/ShapeRenderer.cs b/Xamarin.Forms.Platform.Android/Shapes/ShapeRenderer.cs index 3c0137178..7a70eac8d 100644 --- a/Xamarin.Forms.Platform.Android/Shapes/ShapeRenderer.cs +++ b/Xamarin.Forms.Platform.Android/Shapes/ShapeRenderer.cs @@ -41,6 +41,13 @@ namespace Xamarin.Forms.Platform.Android UpdateStrokeLineCap(); UpdateStrokeLineJoin(); UpdateStrokeMiterLimit(); + + if (!args.NewElement.Bounds.IsEmpty) + { + _height = Element.Height; + _width = Element.Width; + UpdateSize(); + } } } diff --git a/Xamarin.Forms.Platform.iOS.UnitTests/AssertionExtensions.cs b/Xamarin.Forms.Platform.iOS.UnitTests/AssertionExtensions.cs index 5b2d9a5fa..3b2e51e8a 100644 --- a/Xamarin.Forms.Platform.iOS.UnitTests/AssertionExtensions.cs +++ b/Xamarin.Forms.Platform.iOS.UnitTests/AssertionExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Threading.Tasks; using CoreGraphics; using NUnit.Framework; using UIKit; @@ -14,6 +15,13 @@ namespace Xamarin.Forms.Platform.iOS.UnitTests return $"Expected {expectedColor} at point {x},{y} in renderered view. This is what it looked like:{imageAsString}"; } + public static string CreateColorError(this UIImage bitmap, string message) + { + var data = bitmap.AsPNG(); + var imageAsString = data.GetBase64EncodedString(Foundation.NSDataBase64EncodingOptions.None); + return $"{message}. This is what it looked like:{imageAsString}"; + } + public static UIImage ToBitmap(this UIView view) { var imageRect = new CGRect(0, 0, view.Frame.Width, view.Frame.Height); @@ -151,5 +159,53 @@ namespace Xamarin.Forms.Platform.iOS.UnitTests var bitmap = view.ToBitmap(); return bitmap.AssertColorAtTopRight(expectedColor); } + + public static UIImage AssertContainsColor(this UIView view, UIColor expectedColor) + { + return view.ToBitmap().AssertContainsColor(expectedColor); + } + + public static UIImage AssertContainsColor(this UIImage bitmap, UIColor expectedColor) + { + for (int x = 0; x < bitmap.Size.Width; x++) + { + for (int y = 0; y < bitmap.Size.Height; y++) + { + if (ColorComparison.ARGBEquivalent(bitmap.ColorAtPoint(x, y), expectedColor)) + { + return bitmap; + } + } + } + + Assert.Fail(CreateColorError(bitmap, $"Color {expectedColor} not found.")); + return bitmap; + } + + public static async Task AssertEqualsAsync(this UIImage expectedBitmap, UIImage actualBitmap) + { + if(!actualBitmap.AsPNG().IsEqual(expectedBitmap.AsPNG())) + { + string failureMessage = null; + await Device.InvokeOnMainThreadAsync(() => + { + var view = new UIView(); + UIImageView actualView = new UIImageView() { Image = actualBitmap }; + UIImageView expectedView = new UIImageView() { Image = expectedBitmap }; + + actualView.Frame = new CGRect(0, 0, actualBitmap.Size.Width, actualBitmap.Size.Height); + expectedView.Frame = new CGRect(0, actualBitmap.Size.Height + 40, expectedBitmap.Size.Width, expectedBitmap.Size.Height); + + view.Frame = new CGRect(0, 0, + actualView.Frame.Width + expectedView.Frame.Width, + actualView.Frame.Height + expectedView.Frame.Height); + + view.AddSubviews(actualView, expectedView); + failureMessage = CreateColorError(view.ToBitmap(), "Actual (top) vs Expected (bottom)"); + }); + + Assert.Fail(failureMessage); + } + } } } \ No newline at end of file diff --git a/Xamarin.Forms.Platform.iOS.UnitTests/ShapeTests.cs b/Xamarin.Forms.Platform.iOS.UnitTests/ShapeTests.cs new file mode 100644 index 000000000..616c6be8c --- /dev/null +++ b/Xamarin.Forms.Platform.iOS.UnitTests/ShapeTests.cs @@ -0,0 +1,37 @@ +using System.Collections; +using System.Threading.Tasks; +using NUnit.Framework; +using UIKit; +using Xamarin.Forms.Shapes; +using static Xamarin.Forms.Core.UITests.NumericExtensions; +using static Xamarin.Forms.Core.UITests.ParsingUtils; + +namespace Xamarin.Forms.Platform.iOS.UnitTests +{ + [TestFixture] + public class ShapeTests : PlatformTestFixture + { + public ShapeTests() + { + } + + [Test, Category("Shape")] + [Description("Reused ShapeView Renderers Correctly")] + public async Task ReusedShapeViewReRenderers() + { + var view = new Xamarin.Forms.Shapes.Rectangle + { + Fill = SolidColorBrush.Purple, + HeightRequest = 21, + WidthRequest = 21, + Stroke = SolidColorBrush.Purple + }; + + var expected = await GetRendererProperty(view, (ver) => ver.NativeView.ToBitmap(), requiresLayout: true); + + var actual = await GetRendererProperty(view, (ver) => ver.NativeView.ToBitmap(), requiresLayout: true); + + await expected.AssertEqualsAsync(actual); + } + } +} diff --git a/Xamarin.Forms.Platform.iOS.UnitTests/Xamarin.Forms.Platform.iOS.UnitTests.csproj b/Xamarin.Forms.Platform.iOS.UnitTests/Xamarin.Forms.Platform.iOS.UnitTests.csproj index 0850a764e..4861a684a 100644 --- a/Xamarin.Forms.Platform.iOS.UnitTests/Xamarin.Forms.Platform.iOS.UnitTests.csproj +++ b/Xamarin.Forms.Platform.iOS.UnitTests/Xamarin.Forms.Platform.iOS.UnitTests.csproj @@ -69,6 +69,7 @@ + diff --git a/Xamarin.Forms.Platform.iOS/Shapes/EllipseRenderer.cs b/Xamarin.Forms.Platform.iOS/Shapes/EllipseRenderer.cs index 82bb616ad..7752421e8 100644 --- a/Xamarin.Forms.Platform.iOS/Shapes/EllipseRenderer.cs +++ b/Xamarin.Forms.Platform.iOS/Shapes/EllipseRenderer.cs @@ -17,7 +17,7 @@ namespace Xamarin.Forms.Platform.MacOS protected override void OnElementChanged(ElementChangedEventArgs args) { - if (Control == null) + if (Control == null && args.NewElement != null) { SetNativeControl(new EllipseView()); } diff --git a/Xamarin.Forms.Platform.iOS/Shapes/LineRenderer.cs b/Xamarin.Forms.Platform.iOS/Shapes/LineRenderer.cs index fab2889df..5bd2208ef 100644 --- a/Xamarin.Forms.Platform.iOS/Shapes/LineRenderer.cs +++ b/Xamarin.Forms.Platform.iOS/Shapes/LineRenderer.cs @@ -19,7 +19,7 @@ namespace Xamarin.Forms.Platform.MacOS protected override void OnElementChanged(ElementChangedEventArgs args) { - if (Control == null) + if (Control == null && args.NewElement != null) { SetNativeControl(new LineView()); } diff --git a/Xamarin.Forms.Platform.iOS/Shapes/PathRenderer.cs b/Xamarin.Forms.Platform.iOS/Shapes/PathRenderer.cs index 975773684..597b851dd 100644 --- a/Xamarin.Forms.Platform.iOS/Shapes/PathRenderer.cs +++ b/Xamarin.Forms.Platform.iOS/Shapes/PathRenderer.cs @@ -18,7 +18,7 @@ namespace Xamarin.Forms.Platform.MacOS protected override void OnElementChanged(ElementChangedEventArgs args) { - if (Control == null) + if (Control == null && args.NewElement != null) { SetNativeControl(new PathView()); } diff --git a/Xamarin.Forms.Platform.iOS/Shapes/PolygonRenderer.cs b/Xamarin.Forms.Platform.iOS/Shapes/PolygonRenderer.cs index acc762d63..8dff47f20 100644 --- a/Xamarin.Forms.Platform.iOS/Shapes/PolygonRenderer.cs +++ b/Xamarin.Forms.Platform.iOS/Shapes/PolygonRenderer.cs @@ -21,7 +21,7 @@ namespace Xamarin.Forms.Platform.MacOS protected override void OnElementChanged(ElementChangedEventArgs args) { - if (Control == null) + if (Control == null && args.NewElement != null) { SetNativeControl(new PolygonView()); } diff --git a/Xamarin.Forms.Platform.iOS/Shapes/PolylineRenderer.cs b/Xamarin.Forms.Platform.iOS/Shapes/PolylineRenderer.cs index eff7bea48..132d27756 100644 --- a/Xamarin.Forms.Platform.iOS/Shapes/PolylineRenderer.cs +++ b/Xamarin.Forms.Platform.iOS/Shapes/PolylineRenderer.cs @@ -21,7 +21,7 @@ namespace Xamarin.Forms.Platform.MacOS protected override void OnElementChanged(ElementChangedEventArgs args) { - if (Control == null) + if (Control == null && args.NewElement != null) { SetNativeControl(new PolylineView()); } diff --git a/Xamarin.Forms.Platform.iOS/Shapes/RectangleRenderer.cs b/Xamarin.Forms.Platform.iOS/Shapes/RectangleRenderer.cs index 8058f7151..22fe26cb1 100644 --- a/Xamarin.Forms.Platform.iOS/Shapes/RectangleRenderer.cs +++ b/Xamarin.Forms.Platform.iOS/Shapes/RectangleRenderer.cs @@ -22,7 +22,7 @@ namespace Xamarin.Forms.Platform.MacOS protected override void OnElementChanged(ElementChangedEventArgs args) { - if (Control == null) + if (Control == null && args.NewElement != null) { SetNativeControl(new RectangleView()); } diff --git a/Xamarin.Forms.Platform.iOS/Shapes/ShapeRenderer.cs b/Xamarin.Forms.Platform.iOS/Shapes/ShapeRenderer.cs index 979e9f4f1..d5643b5e0 100644 --- a/Xamarin.Forms.Platform.iOS/Shapes/ShapeRenderer.cs +++ b/Xamarin.Forms.Platform.iOS/Shapes/ShapeRenderer.cs @@ -37,6 +37,13 @@ namespace Xamarin.Forms.Platform.MacOS UpdateStrokeLineCap(); UpdateStrokeLineJoin(); UpdateStrokeMiterLimit(); + + if (!args.NewElement.Bounds.IsEmpty) + { + _height = Element.Height; + _width = Element.Width; + UpdateSize(); + } } }