diff options
author | E.Z. Hart <hartez@users.noreply.github.com> | 2017-09-27 13:18:21 -0600 |
---|---|---|
committer | Kangho Hur <kangho.hur@samsung.com> | 2017-10-23 13:33:21 +0900 |
commit | ed5c8b0def0fda9dfeb19d452427094f63b2511c (patch) | |
tree | fb91aedcf78b1a77d2d86b49d3b99cea8273470f | |
parent | 93495b1208e0d38e2520e7f6e07f8bcc668e8604 (diff) | |
download | xamarin-forms-ed5c8b0def0fda9dfeb19d452427094f63b2511c.tar.gz xamarin-forms-ed5c8b0def0fda9dfeb19d452427094f63b2511c.tar.bz2 xamarin-forms-ed5c8b0def0fda9dfeb19d452427094f63b2511c.zip |
Fix context action/tap gesture conflict when tap gesture is on nested view (#1154)
3 files changed, 135 insertions, 1 deletions
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla46363_2.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla46363_2.cs new file mode 100644 index 00000000..8bc88b4f --- /dev/null +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla46363_2.cs @@ -0,0 +1,127 @@ +using System.Collections.Generic; +using Xamarin.Forms.CustomAttributes; +using Xamarin.Forms.Internals; + +#if UITEST +using Xamarin.Forms.Core.UITests; +using Xamarin.UITest; +using NUnit.Framework; +#endif + +namespace Xamarin.Forms.Controls.Issues +{ +#if UITEST + [Category(UITestCategories.Gestures)] + [Category(UITestCategories.ListView)] + [Category(UITestCategories.Cells)] + [Category(UITestCategories.ContextActions)] +#endif + + [Preserve(AllMembers = true)] + [Issue(IssueTracker.Bugzilla, 46363, "TapGestureRecognizer blocks List View Context Actions", + PlatformAffected.Android, issueTestNumber: 1)] + public class Bugzilla46363_2 : TestContentPage + { + // This test case covers a scenario similar to Bugzilla46363, but with the TapGesture + // added to a nested StackLayout within the ViewCell template + + const string Target = "Two"; + const string ContextAction = "Context Action"; + const string TapSuccess = "Tap Success"; + const string TapFailure = "Tap command executed more than once"; + const string ContextSuccess = "Context Menu Success"; + const string Testing = "Testing"; + + static Command s_tapCommand; + static Command s_contextCommand; + + protected override void Init() + { + var list = new List<string> { "One", Target, "Three", "Four" }; + + var lv = new ListView + { + ItemsSource = list, + ItemTemplate = new DataTemplate(typeof(_46363Template_2)) + }; + + var instructions = new Label(); + var result = new Label { Text = Testing }; + + s_tapCommand = new Command(() => + { + if (result.Text == TapSuccess || result.Text == TapFailure) + { + // We want this test to fail if the tap command is executed more than once + result.Text = TapFailure; + } + else + { + result.Text = TapSuccess; + } + }); + + s_contextCommand = new Command(() => + { + result.Text = ContextSuccess; + }); + + var layout = new StackLayout { VerticalOptions = LayoutOptions.Fill, HorizontalOptions = LayoutOptions.Fill }; + + layout.Children.Add(instructions); + layout.Children.Add(result); + layout.Children.Add(lv); + + Content = layout; + } + + [Preserve(AllMembers = true)] + class _46363Template_2 : ViewCell + { + public _46363Template_2() + { + var label = new Label(); + label.SetBinding(Label.TextProperty, "."); + + var innerStackLayout = new StackLayout { Children = { label }, Padding = new Thickness(4, 4, 4, 10) }; + var outerStackLayout = new StackLayout { Children = { innerStackLayout } }; + + View = outerStackLayout; + + ContextActions.Add(new MenuItem + { + Text = ContextAction, + Command = s_contextCommand + }); + + innerStackLayout.GestureRecognizers.Add(new TapGestureRecognizer + { + Command = s_tapCommand + }); + } + } + +#if UITEST + [Test] + public void _46363_2_Tap_Succeeds() + { + RunningApp.WaitForElement(Testing); + RunningApp.Tap(Target); + RunningApp.WaitForElement(TapSuccess); + + // Verify that we aren't also opening the context menu + RunningApp.WaitForNoElement(ContextAction); + } + + [Test] + public void _46363_2_ContextAction_Succeeds() + { + RunningApp.WaitForElement(Testing); + RunningApp.ActivateContextMenu(Target); + RunningApp.WaitForElement(ContextAction); + RunningApp.Tap(ContextAction); + RunningApp.WaitForElement(ContextSuccess); + } +#endif + } +}
\ No newline at end of file diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems index 3009556f..30aa67b4 100644 --- a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems @@ -170,6 +170,7 @@ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla45215.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Bugzilla44500.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Bugzilla46363.cs" /> + <Compile Include="$(MSBuildThisFileDirectory)Bugzilla46363_2.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Bugzilla47548.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Bugzilla52419.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Bugzilla53834.cs" /> diff --git a/Xamarin.Forms.Platform.Android/Cells/ViewCellRenderer.cs b/Xamarin.Forms.Platform.Android/Cells/ViewCellRenderer.cs index 44f2bbbc..46b3321d 100644 --- a/Xamarin.Forms.Platform.Android/Cells/ViewCellRenderer.cs +++ b/Xamarin.Forms.Platform.Android/Cells/ViewCellRenderer.cs @@ -242,7 +242,13 @@ namespace Xamarin.Forms.Platform.Android // LongClick handling from happening. So we need to watch locally for LongPress and if we see it, // trigger the LongClick manually. _watchForLongPress = _viewCell.ContextActions.Count > 0 - && vw.GestureRecognizers.Any(t => t is TapGestureRecognizer); + && HasTapGestureRecognizers(vw); + } + + static bool HasTapGestureRecognizers(View view) + { + return view.GestureRecognizers.Any(t => t is TapGestureRecognizer) + || view.LogicalChildren.OfType<View>().Any(HasTapGestureRecognizers); } void TriggerLongClick() |