зеркало из https://github.com/DeGsoft/maui-linux.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
This commit is contained in:
Родитель
3e0ee965d7
Коммит
ee3c84f051
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -182,6 +182,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)Bugzilla41271.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)_Template.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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче