--- /dev/null
+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
+ }
+}
<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
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";
#endregion
- internal class DefaultRenderer : VisualElementRenderer<View>
+ internal class DefaultRenderer : VisualElementRenderer<View>, ILayoutChanges
{
public bool NotReallyHandled { get; private set; }
IOnTouchListener _touchListener;
_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)
_renderer.Element.ChildrenReordered -= _childReorderedHandler;
}
+
+ if (_renderer.View is ILayoutChanges layout)
+ layout.LayoutChange -= OnInitialLayoutChange;
+
_renderer = null;
}
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++)
{
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);
}
}
}
<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