From a6c0107fbdda75e5d80b34b2faf2a305969c003d Mon Sep 17 00:00:00 2001 From: Youssef Victor Date: Fri, 13 Sep 2024 19:24:51 +0300 Subject: [PATCH] fix(reg): Workaround Gallery measure issue on Android --- ...inPage_d6cd66944958ced0c513e0a04797b51d.cs | 14 +++-------- ...inPage_d6cd66944958ced0c513e0a04797b51d.cs | 7 ++---- ...ionary_92716e07ff456818f6d4125e055d4d57.cs | 17 +++---------- ...inPage_d6cd66944958ced0c513e0a04797b51d.cs | 7 ++---- ...mplate_66bf0a54f1801c397a6fa4930a237eca.cs | 7 ++---- .../XamlGenerator/XamlFileGenerator.cs | 7 ++---- .../Tests/Windows_UI_Xaml/Given_UIElement.cs | 2 +- .../Extensions/ViewExtensions.Android.cs | 5 ++++ src/Uno.UI/UI/Xaml/ILayouterElement.cs | 7 +++++- src/Uno.UI/UI/Xaml/Media/VisualTreeHelper.cs | 25 +++++++++++++++++++ src/Uno.UI/UI/Xaml/UIElement.cs | 3 +++ 11 files changed, 56 insertions(+), 45 deletions(-) diff --git a/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/SOSLIIOFDOTAFE/XamlCodeGenerator_MainPage_d6cd66944958ced0c513e0a04797b51d.cs b/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/SOSLIIOFDOTAFE/XamlCodeGenerator_MainPage_d6cd66944958ced0c513e0a04797b51d.cs index dd263452a3de..42943354fc57 100644 --- a/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/SOSLIIOFDOTAFE/XamlCodeGenerator_MainPage_d6cd66944958ced0c513e0a04797b51d.cs +++ b/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/SOSLIIOFDOTAFE/XamlCodeGenerator_MainPage_d6cd66944958ced0c513e0a04797b51d.cs @@ -389,11 +389,8 @@ public _View Build(object __ResourceOwner_1) } if (__rootInstance is DependencyObject d) { - if (global::Microsoft.UI.Xaml.NameScope.GetNameScope(d) == null) - { - global::Microsoft.UI.Xaml.NameScope.SetNameScope(d, __nameScope); - __nameScope.Owner = d; - } + global::Microsoft.UI.Xaml.NameScope.SetNameScope(d, __nameScope); + __nameScope.Owner = d; global::Uno.UI.FrameworkElementHelper.AddObjectReference(d, this); } return __rootInstance; @@ -444,11 +441,8 @@ public _View Build(object __ResourceOwner_1) ; if (__rootInstance is DependencyObject d) { - if (global::Microsoft.UI.Xaml.NameScope.GetNameScope(d) == null) - { - global::Microsoft.UI.Xaml.NameScope.SetNameScope(d, __nameScope); - __nameScope.Owner = d; - } + global::Microsoft.UI.Xaml.NameScope.SetNameScope(d, __nameScope); + __nameScope.Owner = d; global::Uno.UI.FrameworkElementHelper.AddObjectReference(d, this); } return __rootInstance; diff --git a/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/SOSLIOFPLR/XamlCodeGenerator_MainPage_d6cd66944958ced0c513e0a04797b51d.cs b/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/SOSLIOFPLR/XamlCodeGenerator_MainPage_d6cd66944958ced0c513e0a04797b51d.cs index f0729493fa25..79e3a4cbd214 100644 --- a/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/SOSLIOFPLR/XamlCodeGenerator_MainPage_d6cd66944958ced0c513e0a04797b51d.cs +++ b/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/SOSLIOFPLR/XamlCodeGenerator_MainPage_d6cd66944958ced0c513e0a04797b51d.cs @@ -244,11 +244,8 @@ public _View Build(object __ResourceOwner_1) } if (__rootInstance is DependencyObject d) { - if (global::Microsoft.UI.Xaml.NameScope.GetNameScope(d) == null) - { - global::Microsoft.UI.Xaml.NameScope.SetNameScope(d, __nameScope); - __nameScope.Owner = d; - } + global::Microsoft.UI.Xaml.NameScope.SetNameScope(d, __nameScope); + __nameScope.Owner = d; global::Uno.UI.FrameworkElementHelper.AddObjectReference(d, this); } return __rootInstance; diff --git a/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/TDBMIDTIRD/XamlCodeGenerator_MyResourceDictionary_92716e07ff456818f6d4125e055d4d57.cs b/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/TDBMIDTIRD/XamlCodeGenerator_MyResourceDictionary_92716e07ff456818f6d4125e055d4d57.cs index 807ba550ca6a..8d48ae6c8249 100644 --- a/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/TDBMIDTIRD/XamlCodeGenerator_MyResourceDictionary_92716e07ff456818f6d4125e055d4d57.cs +++ b/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/TDBMIDTIRD/XamlCodeGenerator_MyResourceDictionary_92716e07ff456818f6d4125e055d4d57.cs @@ -100,11 +100,8 @@ public _View Build(object __ResourceOwner_1) } if (__rootInstance is DependencyObject d) { - if (global::Microsoft.UI.Xaml.NameScope.GetNameScope(d) == null) - { - global::Microsoft.UI.Xaml.NameScope.SetNameScope(d, __nameScope); - __nameScope.Owner = d; - } + global::Microsoft.UI.Xaml.NameScope.SetNameScope(d, __nameScope); + __nameScope.Owner = d; global::Uno.UI.FrameworkElementHelper.AddObjectReference(d, this); } return __rootInstance; @@ -266,11 +263,8 @@ public _View Build(object __ResourceOwner_1) } if (__rootInstance is DependencyObject d) { - if (global::Microsoft.UI.Xaml.NameScope.GetNameScope(d) == null) - { global::Microsoft.UI.Xaml.NameScope.SetNameScope(d, __nameScope); __nameScope.Owner = d; - } global::Uno.UI.FrameworkElementHelper.AddObjectReference(d, this); } return __rootInstance; @@ -355,11 +349,8 @@ public _View Build(object __ResourceOwner_1) } if (__rootInstance is DependencyObject d) { - if (global::Microsoft.UI.Xaml.NameScope.GetNameScope(d) == null) - { - global::Microsoft.UI.Xaml.NameScope.SetNameScope(d, __nameScope); - __nameScope.Owner = d; - } + global::Microsoft.UI.Xaml.NameScope.SetNameScope(d, __nameScope); + __nameScope.Owner = d; global::Uno.UI.FrameworkElementHelper.AddObjectReference(d, this); } return __rootInstance; diff --git a/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/TTIXLE/XamlCodeGenerator_MainPage_d6cd66944958ced0c513e0a04797b51d.cs b/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/TTIXLE/XamlCodeGenerator_MainPage_d6cd66944958ced0c513e0a04797b51d.cs index 3c3a8c59ae5b..4d2e50ff7bf7 100644 --- a/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/TTIXLE/XamlCodeGenerator_MainPage_d6cd66944958ced0c513e0a04797b51d.cs +++ b/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/TTIXLE/XamlCodeGenerator_MainPage_d6cd66944958ced0c513e0a04797b51d.cs @@ -369,11 +369,8 @@ public _View Build(object __ResourceOwner_1) ; if (__rootInstance is DependencyObject d) { - if (global::Microsoft.UI.Xaml.NameScope.GetNameScope(d) == null) - { - global::Microsoft.UI.Xaml.NameScope.SetNameScope(d, __nameScope); - __nameScope.Owner = d; - } + global::Microsoft.UI.Xaml.NameScope.SetNameScope(d, __nameScope); + __nameScope.Owner = d; global::Uno.UI.FrameworkElementHelper.AddObjectReference(d, this); } return __rootInstance; diff --git a/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/WBENIT/XamlCodeGenerator_Binding_ElementName_In_Template_66bf0a54f1801c397a6fa4930a237eca.cs b/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/WBENIT/XamlCodeGenerator_Binding_ElementName_In_Template_66bf0a54f1801c397a6fa4930a237eca.cs index 2bfcbd8de737..ddc726a72c3d 100644 --- a/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/WBENIT/XamlCodeGenerator_Binding_ElementName_In_Template_66bf0a54f1801c397a6fa4930a237eca.cs +++ b/src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/WBENIT/XamlCodeGenerator_Binding_ElementName_In_Template_66bf0a54f1801c397a6fa4930a237eca.cs @@ -164,11 +164,8 @@ public _View Build(object __ResourceOwner_1) } if (__rootInstance is DependencyObject d) { - if (global::Microsoft.UI.Xaml.NameScope.GetNameScope(d) == null) - { - global::Microsoft.UI.Xaml.NameScope.SetNameScope(d, __nameScope); - __nameScope.Owner = d; - } + global::Microsoft.UI.Xaml.NameScope.SetNameScope(d, __nameScope); + __nameScope.Owner = d; global::Uno.UI.FrameworkElementHelper.AddObjectReference(d, this); } return __rootInstance; diff --git a/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs b/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs index 1b715a61074e..6b71f278d426 100644 --- a/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs +++ b/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs @@ -953,11 +953,8 @@ private void BuildChildSubclasses(IIndentedStringBuilder writer, bool isTopLevel using (writer.BlockInvariant("if (__rootInstance is DependencyObject d)", kvp.Value.ReturnType)) { - using (writer.BlockInvariant("if (global::Microsoft.UI.Xaml.NameScope.GetNameScope(d) == null)", kvp.Value.ReturnType)) - { - writer.AppendLineIndented("global::Microsoft.UI.Xaml.NameScope.SetNameScope(d, __nameScope);"); - writer.AppendLineIndented("__nameScope.Owner = d;"); - } + writer.AppendLineIndented("global::Microsoft.UI.Xaml.NameScope.SetNameScope(d, __nameScope);"); + writer.AppendLineIndented("__nameScope.Owner = d;"); writer.AppendLineIndented("global::Uno.UI.FrameworkElementHelper.AddObjectReference(d, this);"); } diff --git a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml/Given_UIElement.cs b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml/Given_UIElement.cs index fa8acc766dd1..ed6fb73898b3 100644 --- a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml/Given_UIElement.cs +++ b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml/Given_UIElement.cs @@ -938,7 +938,7 @@ public async Task When_InvalidatingMeasureExplicitly() using var _ = new AssertionScope(); - ctl1.MeasureCount.Should().Be(1); + ctl1.MeasureCount.Should().Be(2); ctl2.MeasureCount.Should().Be(2); ctl3.MeasureCount.Should().Be(1); diff --git a/src/Uno.UI/Extensions/ViewExtensions.Android.cs b/src/Uno.UI/Extensions/ViewExtensions.Android.cs index 4ac82ffcda42..c6c2124279c3 100644 --- a/src/Uno.UI/Extensions/ViewExtensions.Android.cs +++ b/src/Uno.UI/Extensions/ViewExtensions.Android.cs @@ -21,6 +21,7 @@ using Android.Views.Animations; using Microsoft.UI.Xaml.Controls; using Uno.UI.Controls; +using Microsoft.UI.Xaml.Media; namespace Uno.UI { @@ -705,6 +706,10 @@ public static string ShowLocalVisualTree(this ViewGroup viewGroup, int fromHeigh { root = parent; } + else if (root is DependencyObject @do && VisualTreeHelper.GetParent(@do) is ViewGroup managedParent) + { + root = managedParent; + } else { break; diff --git a/src/Uno.UI/UI/Xaml/ILayouterElement.cs b/src/Uno.UI/UI/Xaml/ILayouterElement.cs index 9d43be9e9e72..68f5f0d7d2fa 100644 --- a/src/Uno.UI/UI/Xaml/ILayouterElement.cs +++ b/src/Uno.UI/UI/Xaml/ILayouterElement.cs @@ -74,6 +74,7 @@ internal static bool DoMeasure(this ILayouterElement element, Size availableSize if (isDirty || frameworkElement is null) { // We must reset the flag **BEFORE** doing the actual measure, so the elements are able to re-invalidate themselves + // TODO: We are not controlling measure dirty path on Android. If we did in future, we must clear it here as well. frameworkElement?.ClearLayoutFlags(UIElement.LayoutFlag.MeasureDirty); // The dirty flag is explicitly set on this element @@ -91,7 +92,9 @@ internal static bool DoMeasure(this ILayouterElement element, Size availableSize LayoutInformation.SetAvailableSize(element, availableSize); } - return true; // end of isDirty processing + // TODO: This is NOT correct. + // We shouldn't return here. Skipping children measure is incorrect but fixing it on Android isn't trivial. + return true; } // The measure dirty flag is set on one of the descendents: @@ -110,6 +113,8 @@ internal static bool DoMeasure(this ILayouterElement element, Size availableSize { var previousDesiredSize = childAsUIElement.m_desiredSize; childAsUIElement.EnsureLayoutStorage(); + + // TODO: This is NOT correct. This should call DoMeasure (the same method we are in currently!) element.Layouter.MeasureChild(child, childAsUIElement.m_previousAvailableSize); var newDesiredSize = childAsUIElement.m_desiredSize; if (newDesiredSize != previousDesiredSize) diff --git a/src/Uno.UI/UI/Xaml/Media/VisualTreeHelper.cs b/src/Uno.UI/UI/Xaml/Media/VisualTreeHelper.cs index ec4af5e05f56..0e74bb600b47 100644 --- a/src/Uno.UI/UI/Xaml/Media/VisualTreeHelper.cs +++ b/src/Uno.UI/UI/Xaml/Media/VisualTreeHelper.cs @@ -393,6 +393,31 @@ internal static void AddChild(UIElement view, UIElement child) { #if __ANDROID__ view.AddView(child); + + // Reset to original (invalidated) state + child.ResetLayoutFlags(); + if (view.IsMeasureDirtyPathDisabled) + { + FrameworkElementHelper.SetUseMeasurePathDisabled(child); // will invalidate too + } + else + { + child.InvalidateMeasure(); + } + + if (view.IsArrangeDirtyPathDisabled) + { + FrameworkElementHelper.SetUseArrangePathDisabled(child); // will invalidate too + } + else + { + child.InvalidateArrange(); + } + + // Force a new measure of this element (the parent of the new child) + view.InvalidateMeasure(); + view.InvalidateArrange(); + #elif __IOS__ || __MACOS__ view.AddSubview(child); #elif __CROSSRUNTIME__ diff --git a/src/Uno.UI/UI/Xaml/UIElement.cs b/src/Uno.UI/UI/Xaml/UIElement.cs index aeb9fcab2327..4099ae96db22 100644 --- a/src/Uno.UI/UI/Xaml/UIElement.cs +++ b/src/Uno.UI/UI/Xaml/UIElement.cs @@ -1149,6 +1149,9 @@ public void InvalidateMeasure() // Use a non-virtual version of the RequestLayout method, for performance. base.RequestLayout(); SetLayoutFlags(LayoutFlag.MeasureDirty); + + // HACK: Android's implementation of measure/arrange is not accurate. See comments in LayouterElementExtensions.DoMeasure + (VisualTreeHelper.GetParent(this) as UIElement)?.InvalidateMeasure(); #elif __IOS__ SetNeedsLayout(); SetLayoutFlags(LayoutFlag.MeasureDirty);