Give layouts a chance to handle touch events after passing though immediate children (#902)
* Repro for Bugzilla 55912 * Automate test * Give the layout a chance to actually handle gestures before bubbling up
This commit is contained in:
Родитель
40dff0a54c
Коммит
adac0fcc38
|
@ -0,0 +1,95 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using Xamarin.Forms.CustomAttributes;
|
||||
using Xamarin.Forms.Internals;
|
||||
#if UITEST
|
||||
using NUnit.Framework;
|
||||
|
||||
#endif
|
||||
|
||||
namespace Xamarin.Forms.Controls.Issues
|
||||
{
|
||||
[Preserve(AllMembers = true)]
|
||||
[Issue(IssueTracker.Bugzilla, 955912, "Tap event not always propagated to containing Grid/StackLayout",
|
||||
PlatformAffected.Android)]
|
||||
public class Bugzilla55912 : TestContentPage
|
||||
{
|
||||
const string Success = "Success";
|
||||
const string GridLabelId = "GridLabel";
|
||||
const string StackLabelId = "StackLabel";
|
||||
|
||||
protected override void Init()
|
||||
{
|
||||
var layout = new Grid();
|
||||
|
||||
layout.RowDefinitions.Add(new RowDefinition { Height = GridLength.Star });
|
||||
layout.RowDefinitions.Add(new RowDefinition { Height = GridLength.Star });
|
||||
layout.RowDefinitions.Add(new RowDefinition { Height = GridLength.Star });
|
||||
|
||||
var testGrid = new Grid { BackgroundColor = Color.Red };
|
||||
var gridLabel = new Label
|
||||
{
|
||||
AutomationId = GridLabelId,
|
||||
Text = "This is a Grid with a TapGesture",
|
||||
FontSize = 24,
|
||||
BackgroundColor = Color.Green
|
||||
};
|
||||
Grid.SetRow(testGrid, 1);
|
||||
testGrid.Children.Add(gridLabel);
|
||||
|
||||
var testStack = new StackLayout { BackgroundColor = Color.Default };
|
||||
var stackLabel = new Label
|
||||
{
|
||||
AutomationId = StackLabelId,
|
||||
Text = "This StackLayout also has a TapGesture",
|
||||
FontSize = 24,
|
||||
BackgroundColor = Color.Green
|
||||
};
|
||||
Grid.SetRow(testStack, 2);
|
||||
testStack.Children.Add(stackLabel);
|
||||
|
||||
layout.Children.Add(testGrid);
|
||||
layout.Children.Add(testStack);
|
||||
|
||||
Content = layout;
|
||||
|
||||
testGrid.GestureRecognizers.Add(new TapGestureRecognizer
|
||||
{
|
||||
NumberOfTapsRequired = 1,
|
||||
Command = new Command(() =>
|
||||
{
|
||||
Debug.WriteLine($"***** TestGrid Tapped: {DateTime.Now} *****");
|
||||
layout.Children.Add(new Label { AutomationId = Success, Text = Success });
|
||||
})
|
||||
});
|
||||
|
||||
testStack.GestureRecognizers.Add(new TapGestureRecognizer
|
||||
{
|
||||
NumberOfTapsRequired = 1,
|
||||
Command = new Command(() =>
|
||||
{
|
||||
Debug.WriteLine($"***** TestStack Tapped: {DateTime.Now} *****");
|
||||
layout.Children.Add(new Label { AutomationId = Success, Text = Success });
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#if UITEST
|
||||
[Test]
|
||||
public void GestureBubblingInStackLayout()
|
||||
{
|
||||
RunningApp.WaitForElement(StackLabelId);
|
||||
RunningApp.Tap(StackLabelId);
|
||||
RunningApp.WaitForElement(Success);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GestureBubblingInGrid()
|
||||
{
|
||||
RunningApp.WaitForElement(GridLabelId);
|
||||
RunningApp.Tap(GridLabelId);
|
||||
RunningApp.WaitForElement(Success);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -196,6 +196,7 @@
|
|||
</Compile>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla52266.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla53445.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla55912.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)CarouselAsync.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla34561.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla34727.cs" />
|
||||
|
|
|
@ -1070,9 +1070,12 @@ namespace Xamarin.Forms.Platform.Android
|
|||
|
||||
if (result && _notReallyHandled)
|
||||
{
|
||||
// If the child control returned true from its touch event handler but signalled that it was a fake "true", leave the event unhandled
|
||||
// so parent controls have the opportunity
|
||||
return false;
|
||||
// If the child control returned true from its touch event handler but signalled that it was a fake "true", then we
|
||||
// don't consider the event truly "handled" yet.
|
||||
// Since a child control short-circuited the normal dispatchTouchEvent stuff, this layout never got the chance for
|
||||
// IOnTouchListener.OnTouch and the OnTouchEvent override to try handling the touches; we'll do that now
|
||||
|
||||
return OnTouchEvent(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
Загрузка…
Ссылка в новой задаче