From: Samantha Houts Date: Tue, 27 Sep 2016 18:12:49 +0000 (-0700) Subject: [Win] Will arrange native children of custom renderers (opt-in) (#322) X-Git-Tag: beta-2.3.4-pre1~120 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ee3c84f05175934a9d847a3d867e370c4b301a99;p=platform%2Fupstream%2Fxamarin-forms.git [Win] Will arrange native children of custom renderers (opt-in) (#322) * Add repro for 42602 * [Win] Add option to arrange native children * [Win] Don't allocate arrangedChildren unless required --- diff --git a/Xamarin.Forms.ControlGallery.Windows/CustomRenderers.cs b/Xamarin.Forms.ControlGallery.Windows/CustomRenderers.cs new file mode 100644 index 0000000..391aed2 --- /dev/null +++ b/Xamarin.Forms.ControlGallery.Windows/CustomRenderers.cs @@ -0,0 +1,57 @@ +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Shapes; +using Xamarin.Forms.Platform.WinRT; + +[assembly: ExportRenderer(typeof(Xamarin.Forms.Controls.Bugzilla42602.TextBoxView), typeof(Xamarin.Forms.ControlGallery.Windows.TextBoxViewRenderer))] +namespace Xamarin.Forms.ControlGallery.Windows +{ + public class TextBoxViewRenderer : BoxViewRenderer + { + Canvas m_Canvas; + + protected override void OnElementChanged(ElementChangedEventArgs e) + { + base.OnElementChanged(e); + + ArrangeNativeChildren = true; + + if (m_Canvas != null) + Children.Remove(m_Canvas); + + m_Canvas = new Canvas() + { + Width = 200, + Height = 200, + Background = new SolidColorBrush(global::Windows.UI.Color.FromArgb(0, 255, 255, 255)), + IsHitTestVisible = false + }; + + Children.Add(m_Canvas); + + //ellipse + Shape ellipse = new Ellipse() + { + Width = 100, + Height = 100, + Fill = new SolidColorBrush(global::Windows.UI.Color.FromArgb(255, 255, 0, 0)), + + }; + Canvas.SetLeft(ellipse, 0); + Canvas.SetTop(ellipse, 0); + m_Canvas.Children.Add(ellipse); + + //text + TextBlock text = new TextBlock() + { + FontSize = 50, + FontWeight = global::Windows.UI.Text.FontWeights.Normal, + Text = "hello world", + Foreground = new SolidColorBrush(global::Windows.UI.Color.FromArgb(255, 255, 0, 0)) + }; + Canvas.SetLeft(text, 0); + Canvas.SetTop(text, 150); + m_Canvas.Children.Add(text); + } + } +} diff --git a/Xamarin.Forms.ControlGallery.Windows/Xamarin.Forms.ControlGallery.Windows.csproj b/Xamarin.Forms.ControlGallery.Windows/Xamarin.Forms.ControlGallery.Windows.csproj index aa8f862..6252820 100644 --- a/Xamarin.Forms.ControlGallery.Windows/Xamarin.Forms.ControlGallery.Windows.csproj +++ b/Xamarin.Forms.ControlGallery.Windows/Xamarin.Forms.ControlGallery.Windows.csproj @@ -141,6 +141,7 @@ + MainPage.xaml diff --git a/Xamarin.Forms.ControlGallery.WindowsPhone/CustomRenderers.cs b/Xamarin.Forms.ControlGallery.WindowsPhone/CustomRenderers.cs new file mode 100644 index 0000000..2f6cae9 --- /dev/null +++ b/Xamarin.Forms.ControlGallery.WindowsPhone/CustomRenderers.cs @@ -0,0 +1,57 @@ +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Shapes; +using Xamarin.Forms.Platform.WinRT; + +[assembly: ExportRenderer(typeof(Xamarin.Forms.Controls.Bugzilla42602.TextBoxView), typeof(Xamarin.Forms.ControlGallery.WindowsPhone.TextBoxViewRenderer))] +namespace Xamarin.Forms.ControlGallery.WindowsPhone +{ + public class TextBoxViewRenderer : BoxViewRenderer + { + Canvas m_Canvas; + + protected override void OnElementChanged(ElementChangedEventArgs e) + { + base.OnElementChanged(e); + + ArrangeNativeChildren = true; + + if (m_Canvas != null) + Children.Remove(m_Canvas); + + m_Canvas = new Canvas() + { + Width = 200, + Height = 200, + Background = new SolidColorBrush(global::Windows.UI.Color.FromArgb(0, 255, 255, 255)), + IsHitTestVisible = false + }; + + Children.Add(m_Canvas); + + //ellipse + Shape ellipse = new Ellipse() + { + Width = 100, + Height = 100, + Fill = new SolidColorBrush(global::Windows.UI.Color.FromArgb(255, 255, 0, 0)), + + }; + Canvas.SetLeft(ellipse, 0); + Canvas.SetTop(ellipse, 0); + m_Canvas.Children.Add(ellipse); + + //text + TextBlock text = new TextBlock() + { + FontSize = 50, + FontWeight = global::Windows.UI.Text.FontWeights.Normal, + Text = "hello world", + Foreground = new SolidColorBrush(global::Windows.UI.Color.FromArgb(255, 255, 0, 0)) + }; + Canvas.SetLeft(text, 0); + Canvas.SetTop(text, 150); + m_Canvas.Children.Add(text); + } + } +} diff --git a/Xamarin.Forms.ControlGallery.WindowsPhone/Xamarin.Forms.ControlGallery.WindowsPhone.csproj b/Xamarin.Forms.ControlGallery.WindowsPhone/Xamarin.Forms.ControlGallery.WindowsPhone.csproj index a856543..349b0b4 100644 --- a/Xamarin.Forms.ControlGallery.WindowsPhone/Xamarin.Forms.ControlGallery.WindowsPhone.csproj +++ b/Xamarin.Forms.ControlGallery.WindowsPhone/Xamarin.Forms.ControlGallery.WindowsPhone.csproj @@ -117,6 +117,7 @@ App.xaml + MainPage.xaml diff --git a/Xamarin.Forms.ControlGallery.WindowsUniversal/CustomRenderers.cs b/Xamarin.Forms.ControlGallery.WindowsUniversal/CustomRenderers.cs new file mode 100644 index 0000000..8d937d4 --- /dev/null +++ b/Xamarin.Forms.ControlGallery.WindowsUniversal/CustomRenderers.cs @@ -0,0 +1,57 @@ +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Shapes; +using Xamarin.Forms.Platform.UWP; + +[assembly: ExportRenderer(typeof(Xamarin.Forms.Controls.Bugzilla42602.TextBoxView), typeof(Xamarin.Forms.ControlGallery.WindowsUniversal.TextBoxViewRenderer))] +namespace Xamarin.Forms.ControlGallery.WindowsUniversal +{ + public class TextBoxViewRenderer : BoxViewRenderer + { + Canvas m_Canvas; + + protected override void OnElementChanged(ElementChangedEventArgs e) + { + base.OnElementChanged(e); + + ArrangeNativeChildren = true; + + if (m_Canvas != null) + Children.Remove(m_Canvas); + + m_Canvas = new Canvas() + { + Width = 200, + Height = 200, + Background = new SolidColorBrush(Windows.UI.Color.FromArgb(0, 255, 255, 255)), + IsHitTestVisible = false + }; + + Children.Add(m_Canvas); + + //ellipse + Shape ellipse = new Ellipse() + { + Width = 100, + Height = 100, + Fill = new SolidColorBrush(Windows.UI.Color.FromArgb(255, 255, 0, 0)), + + }; + Canvas.SetLeft(ellipse, 0); + Canvas.SetTop(ellipse, 0); + m_Canvas.Children.Add(ellipse); + + //text + TextBlock text = new TextBlock() + { + FontSize = 50, + FontWeight = Windows.UI.Text.FontWeights.Normal, + Text = "hello world", + Foreground = new SolidColorBrush(Windows.UI.Color.FromArgb(255, 255, 0, 0)) + }; + Canvas.SetLeft(text, 0); + Canvas.SetTop(text, 150); + m_Canvas.Children.Add(text); + } + } +} diff --git a/Xamarin.Forms.ControlGallery.WindowsUniversal/Xamarin.Forms.ControlGallery.WindowsUniversal.csproj b/Xamarin.Forms.ControlGallery.WindowsUniversal/Xamarin.Forms.ControlGallery.WindowsUniversal.csproj index 58ad67b..7e1847e 100644 --- a/Xamarin.Forms.ControlGallery.WindowsUniversal/Xamarin.Forms.ControlGallery.WindowsUniversal.csproj +++ b/Xamarin.Forms.ControlGallery.WindowsUniversal/Xamarin.Forms.ControlGallery.WindowsUniversal.csproj @@ -164,6 +164,7 @@ App.xaml + MainPage.xaml diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla42602.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla42602.cs new file mode 100644 index 0000000..05e4101 --- /dev/null +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla42602.cs @@ -0,0 +1,39 @@ +using System; + +using Xamarin.Forms.CustomAttributes; +using Xamarin.Forms.Internals; + +namespace Xamarin.Forms.Controls +{ + [Preserve(AllMembers = true)] + [Issue(IssueTracker.Bugzilla, 42602, "[Win] Custom BoxView Renderer Does Not Render All Its Children Elements", PlatformAffected.WinRT)] + public class Bugzilla42602 : TestContentPage + { + AbsoluteLayout content; + + protected override void Init() + { + //background white 800 x 600 square + content = new AbsoluteLayout() + { + BackgroundColor = Color.White, + WidthRequest = 800, + HeightRequest = 800, + VerticalOptions = LayoutOptions.CenterAndExpand, + HorizontalOptions = LayoutOptions.CenterAndExpand + }; + + //test TextBoxView 400 x 400, color gray, should have a red ellipse and a red "hello world" + + var test = new TextBoxView() { WidthRequest = 300, HeightRequest = 300, BackgroundColor = Color.Blue }; + content.Children.Add(test, new Point((content.WidthRequest - test.WidthRequest) / 2f, (content.HeightRequest - test.HeightRequest) / 2f)); + + Content = content; + } + + public class TextBoxView : BoxView + { + + } + } +} 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 c5f46d5..670f286 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 @@ -182,6 +182,7 @@ + diff --git a/Xamarin.Forms.Platform.WinRT/VisualElementRenderer.cs b/Xamarin.Forms.Platform.WinRT/VisualElementRenderer.cs index 3ad826b..b81f73e 100644 --- a/Xamarin.Forms.Platform.WinRT/VisualElementRenderer.cs +++ b/Xamarin.Forms.Platform.WinRT/VisualElementRenderer.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.ComponentModel; using Windows.Foundation; using Windows.UI.Xaml; @@ -28,6 +29,8 @@ namespace Xamarin.Forms.Platform.WinRT protected bool AutoTrack { get; set; } = true; + protected bool ArrangeNativeChildren { get; set; } + IElementController ElementController => Element as IElementController; protected VisualElementTracker Tracker @@ -160,11 +163,14 @@ namespace Xamarin.Forms.Platform.WinRT Element.IsInNativeLayout = true; + var myRect = new Rect(0, 0, finalSize.Width, finalSize.Height); + if (Control != null) { - Control.Arrange(new Rect(0, 0, finalSize.Width, finalSize.Height)); + Control.Arrange(myRect); } + List arrangedChildren = null; for (var i = 0; i < ElementController.LogicalChildren.Count; i++) { var child = ElementController.LogicalChildren[i] as VisualElement; @@ -176,6 +182,30 @@ namespace Xamarin.Forms.Platform.WinRT Rectangle bounds = child.Bounds; renderer.ContainerElement.Arrange(new Rect(bounds.X, bounds.Y, Math.Max(0, bounds.Width), Math.Max(0, bounds.Height))); + + if (ArrangeNativeChildren) + { + if (arrangedChildren == null) + arrangedChildren = new List(); + arrangedChildren.Add(renderer.ContainerElement); + } + } + + if (ArrangeNativeChildren) + { + // in the event that a custom renderer has added native controls, + // we need to be sure to arrange them so that they are laid out. + var nativeChildren = Children; + for (int i = 0; i < nativeChildren.Count; i++) + { + var nativeChild = nativeChildren[i]; + if (arrangedChildren?.Contains(nativeChild) == true) + // don't try to rearrange renderers that were just arranged, + // lest you suffer a layout cycle + continue; + else + nativeChild.Arrange(myRect); + } } Element.IsInNativeLayout = false;