summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorE.Z. Hart <hartez@users.noreply.github.com>2017-09-27 13:18:21 -0600
committerKangho Hur <kangho.hur@samsung.com>2017-10-23 13:33:21 +0900
commited5c8b0def0fda9dfeb19d452427094f63b2511c (patch)
treefb91aedcf78b1a77d2d86b49d3b99cea8273470f
parent93495b1208e0d38e2520e7f6e07f8bcc668e8604 (diff)
downloadxamarin-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)
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla46363_2.cs127
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems1
-rw-r--r--Xamarin.Forms.Platform.Android/Cells/ViewCellRenderer.cs8
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()