[Android] propagate elevation after initial elevation changes android (#6271)
authorShane Neuville <shane94@hotmail.com>
Tue, 28 May 2019 18:56:40 +0000 (12:56 -0600)
committerSamantha Houts <samhouts@users.noreply.github.com>
Tue, 28 May 2019 18:56:40 +0000 (11:56 -0700)
fixes #6262

Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue6262.cs [new file with mode: 0644]
Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems
Xamarin.Forms.Core.UITests.Shared/UITestCategories.cs
Xamarin.Forms.Platform.Android/Platform.cs
Xamarin.Forms.Platform.Android/VisualElementPackager.cs
Xamarin.Forms.Sandbox.Android/Resources/drawable/coffee.png [new file with mode: 0644]
Xamarin.Forms.Sandbox.Android/Xamarin.Forms.Sandbox.Android.csproj

diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue6262.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue6262.cs
new file mode 100644 (file)
index 0000000..7242969
--- /dev/null
@@ -0,0 +1,93 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Text;
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.Forms.Internals;
+
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+using Xamarin.Forms.Core.UITests;
+#endif
+
+namespace Xamarin.Forms.Controls.Issues
+{
+       [Preserve(AllMembers = true)]
+       [Issue(IssueTracker.Github, 6262, "[Bug] Button in Grid gets wrong z-index",
+               PlatformAffected.iOS)]
+#if UITEST
+       [NUnit.Framework.Category(UITestCategories.Layout)]
+#endif
+       public class Issue6262 : TestContentPage
+       {
+               protected override void Init()
+               {
+                       Grid theGrid = null;
+                       theGrid = new Grid() { VerticalOptions = LayoutOptions.FillAndExpand };
+                       SetupGrid(theGrid);
+
+                       Content = new StackLayout()
+                       {
+                               Children =
+                               {
+                                       theGrid,
+                                       new Button()
+                                       {
+                                               Text = "Click this and see if test succeeds. If you don't see failure text then test has passed",
+                                               AutomationId = "RetryTest",
+                                               Command = new Command(() => SetupGrid(theGrid))
+                                       }
+                               }
+                       };
+
+               }
+
+               void SetupGrid(Grid theGrid)
+               {
+                       if(theGrid.Children.Count > 0)
+                               theGrid.Children.Clear();
+
+                       theGrid.Children.Add(
+                               new Button()
+                               {
+                                       HorizontalOptions = LayoutOptions.Fill,
+                                       VerticalOptions = LayoutOptions.Fill,
+                                       Text = "If you can see this the test has failed",
+                                       AutomationId = "ClickMe",
+                                       Command = new Command(() =>
+                                       {
+                                               theGrid.Children.Clear();
+                                               theGrid.Children.Add(new Label() { AutomationId = "Fail", Text = "Test Failed" });
+                                       })
+                               });
+
+                       theGrid.Children.Add(
+                               new Image()
+                               {
+                                       Source = "coffee.png",
+                                       HorizontalOptions = LayoutOptions.Fill,
+                                       VerticalOptions = LayoutOptions.Fill,
+                                       AutomationId = "ClickMe",
+                                       BackgroundColor = Color.Green
+                               });
+               }
+
+#if UITEST
+               [Test]
+               public void ImageShouldLayoutOnTopOfButton()
+               {
+                       RunningApp.WaitForElement("ClickMe");
+                       RunningApp.Tap("ClickMe");
+                       RunningApp.WaitForElement("ClickMe");
+                       RunningApp.WaitForNoElement("Fail");
+                       RunningApp.Tap("RetryTest");
+                       RunningApp.WaitForElement("ClickMe");
+                       RunningApp.Tap("ClickMe");
+                       RunningApp.WaitForElement("ClickMe");
+                       RunningApp.WaitForNoElement("Fail");
+               }
+#endif
+       }
+}
index 1bff20f..3a010ef 100644 (file)
@@ -9,6 +9,7 @@
     <Import_RootNamespace>Xamarin.Forms.Controls.Issues</Import_RootNamespace>
   </PropertyGroup>
   <ItemGroup>
+    <Compile Include="$(MSBuildThisFileDirectory)Issue6262.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Bugzilla59172.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Issue5766.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Issue4684.xaml.cs" />
       <DependentUpon>Issue6130.xaml</DependentUpon>
     </Compile>
   </ItemGroup>
-</Project>
+</Project>
\ No newline at end of file
index 9eab177..9d4f8a0 100644 (file)
@@ -19,6 +19,7 @@
                public const string Image = "Image";
                public const string ImageButton = "ImageButton";
                public const string Label = "Label";
+               public const string Layout = "Layout";
                public const string ListView = "ListView";
                public const string UwpIgnore = "UwpIgnore";
                public const string LifeCycle = "Lifecycle";
index f58eb5a..ad10a23 100644 (file)
@@ -1183,7 +1183,7 @@ namespace Xamarin.Forms.Platform.Android
 
                #endregion
 
-               internal class DefaultRenderer : VisualElementRenderer<View>
+               internal class DefaultRenderer : VisualElementRenderer<View>, ILayoutChanges
                {
                        public bool NotReallyHandled { get; private set; }
                        IOnTouchListener _touchListener;
index 01f1be9..de091ca 100644 (file)
@@ -37,6 +37,21 @@ namespace Xamarin.Forms.Platform.Android
 
                        _renderer = renderer;
                        _renderer.ElementChanged += OnElementChanged;
+
+                       if(renderer.View is ILayoutChanges layout)
+                               layout.LayoutChange += OnInitialLayoutChange;
+               }
+
+               void OnInitialLayoutChange(object sender, AView.LayoutChangeEventArgs e)
+               {
+                       // this is used to adjust any relative elevations on the child elements that still need to settle
+                       // the default elevation is set on Button after it's already added to the view hierarchy
+                       // but this appears to only be the case when the app first starts
+
+                       if (sender is ILayoutChanges layout)
+                               layout.LayoutChange -= OnInitialLayoutChange;
+
+                       EnsureChildOrder(true);
                }
 
                void OnElementChanged(object sender, VisualElementChangedEventArgs e)
@@ -80,6 +95,10 @@ namespace Xamarin.Forms.Platform.Android
 
                                        _renderer.Element.ChildrenReordered -= _childReorderedHandler;
                                }
+
+                               if (_renderer.View is ILayoutChanges layout)
+                                       layout.LayoutChange -= OnInitialLayoutChange;
+
                                _renderer = null;
                        }
 
@@ -141,7 +160,10 @@ namespace Xamarin.Forms.Platform.Android
                                Performance.Stop(reference);
                        }
                }
-               void EnsureChildOrder()
+
+               void EnsureChildOrder() => EnsureChildOrder(false);
+
+               void EnsureChildOrder(bool onlyUpdateElevations)
                {
                        float elevationToSet = 0;
                        for (var i = 0; i < ElementController.LogicalChildren.Count; i++)
@@ -162,12 +184,13 @@ namespace Xamarin.Forms.Platform.Android
                                                        {
                                                                if (elevation > elevationToSet)
                                                                        elevationToSet = elevation;
-
+                                                                                                                               
                                                                r.View.Elevation = elevationToSet;
                                                        }
                                                }
 
-                                               (_renderer.View as ViewGroup)?.BringChildToFront(r.View);
+                                               if(!onlyUpdateElevations)
+                                                       (_renderer.View as ViewGroup)?.BringChildToFront(r.View);
                                        }
                                }
                        }
diff --git a/Xamarin.Forms.Sandbox.Android/Resources/drawable/coffee.png b/Xamarin.Forms.Sandbox.Android/Resources/drawable/coffee.png
new file mode 100644 (file)
index 0000000..350257c
Binary files /dev/null and b/Xamarin.Forms.Sandbox.Android/Resources/drawable/coffee.png differ
index bcae908..c3d72d9 100644 (file)
@@ -93,7 +93,6 @@
     <Folder Include="Resources\drawable-xhdpi\" />
     <Folder Include="Resources\drawable-xxhdpi\" />
     <Folder Include="Resources\drawable-xxxhdpi\" />
-    <Folder Include="Resources\drawable\" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\Stubs\Xamarin.Forms.Platform.Android\Xamarin.Forms.Platform.Android (Forwarders).csproj">
       <Name>Xamarin.Forms.Sandbox</Name>
     </ProjectReference>
   </ItemGroup>
+  <ItemGroup>
+    <AndroidResource Include="Resources\drawable\coffee.png">
+      <Generator>MSBuild:UpdateGeneratedFiles</Generator>
+      <SubType>Designer</SubType>
+    </AndroidResource>
+  </ItemGroup>
   <Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
   <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
 </Project>
\ No newline at end of file