summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamantha Houts <samantha@teamredwall.com>2016-09-27 11:12:49 -0700
committerJason Smith <jason.smith@xamarin.com>2016-09-27 11:13:20 -0700
commit48b91865634df4888a43ea899d107953c5aabd58 (patch)
tree3a37a4065f4499067d77a018c3ce2a60deb846a6
parent33b60324383b5424339119e432137b6d7d898fa8 (diff)
downloadxamarin-forms-48b91865634df4888a43ea899d107953c5aabd58.tar.gz
xamarin-forms-48b91865634df4888a43ea899d107953c5aabd58.tar.bz2
xamarin-forms-48b91865634df4888a43ea899d107953c5aabd58.zip
[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
-rw-r--r--Xamarin.Forms.ControlGallery.Windows/CustomRenderers.cs57
-rw-r--r--Xamarin.Forms.ControlGallery.Windows/Xamarin.Forms.ControlGallery.Windows.csproj1
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsPhone/CustomRenderers.cs57
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsPhone/Xamarin.Forms.ControlGallery.WindowsPhone.csproj1
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsUniversal/CustomRenderers.cs57
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsUniversal/Xamarin.Forms.ControlGallery.WindowsUniversal.csproj1
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla42602.cs39
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems1
-rw-r--r--Xamarin.Forms.Platform.WinRT/VisualElementRenderer.cs32
9 files changed, 245 insertions, 1 deletions
diff --git a/Xamarin.Forms.ControlGallery.Windows/CustomRenderers.cs b/Xamarin.Forms.ControlGallery.Windows/CustomRenderers.cs
new file mode 100644
index 00000000..391aed2e
--- /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<BoxView> 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 aa8f862f..6252820b 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 @@
</Compile>
<Compile Include="BrokenImageSourceHandler.cs" />
<Compile Include="BrokenNativeControl.cs" />
+ <Compile Include="CustomRenderers.cs" />
<Compile Include="MainPage.xaml.cs">
<DependentUpon>MainPage.xaml</DependentUpon>
</Compile>
diff --git a/Xamarin.Forms.ControlGallery.WindowsPhone/CustomRenderers.cs b/Xamarin.Forms.ControlGallery.WindowsPhone/CustomRenderers.cs
new file mode 100644
index 00000000..2f6cae90
--- /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<BoxView> 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 a8565433..349b0b4c 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 @@
<DependentUpon>App.xaml</DependentUpon>
</Compile>
<Compile Include="BrokenNativeControl.cs" />
+ <Compile Include="CustomRenderers.cs" />
<Compile Include="MainPage.xaml.cs">
<DependentUpon>MainPage.xaml</DependentUpon>
</Compile>
diff --git a/Xamarin.Forms.ControlGallery.WindowsUniversal/CustomRenderers.cs b/Xamarin.Forms.ControlGallery.WindowsUniversal/CustomRenderers.cs
new file mode 100644
index 00000000..8d937d49
--- /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<BoxView> 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 58ad67b3..7e1847ea 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 @@
<DependentUpon>App.xaml</DependentUpon>
</Compile>
<Compile Include="BrokenNativeControl.cs" />
+ <Compile Include="CustomRenderers.cs" />
<Compile Include="MainPage.xaml.cs">
<DependentUpon>MainPage.xaml</DependentUpon>
</Compile>
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 00000000..05e41013
--- /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 364b3c44..f7f89173 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
@@ -181,6 +181,7 @@
<Compile Include="$(MSBuildThisFileDirectory)ImageLoadingErrorHandling.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla33561.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla43214.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla42602.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla43161.cs" />
<Compile Include="$(MSBuildThisFileDirectory)_Template.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue1028.cs" />
diff --git a/Xamarin.Forms.Platform.WinRT/VisualElementRenderer.cs b/Xamarin.Forms.Platform.WinRT/VisualElementRenderer.cs
index 3ad826b1..b81f73e3 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<TElement, TNativeElement> 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<UIElement> 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<UIElement>();
+ 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;