summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Controls.Issues
diff options
context:
space:
mode:
authorE.Z. Hart <hartez@users.noreply.github.com>2017-03-29 02:52:45 -0600
committerRui Marinho <me@ruimarinho.net>2017-03-29 09:52:45 +0100
commite55efa2a8e1164d805bc76b0f3ce84999d2f1bb8 (patch)
tree62ef93abac6215010ca9fe719ee03fc414e88bfe /Xamarin.Forms.Controls.Issues
parent90582e977734d40d2023537186ebcf79f826291e (diff)
downloadxamarin-forms-e55efa2a8e1164d805bc76b0f3ce84999d2f1bb8.tar.gz
xamarin-forms-e55efa2a8e1164d805bc76b0f3ce84999d2f1bb8.tar.bz2
xamarin-forms-e55efa2a8e1164d805bc76b0f3ce84999d2f1bb8.zip
Align iOS, Android, Windows handling of tap gesture event bubbling (#842)
* Add test for gesture bubbling behavior on all controls; Make Windows behavior consistent with other platforms; * Fix the stepper test * Make Frame on Android handle tap event bubbling like the other platforms * Formatting changes and query syntax instead of SelectMany
Diffstat (limited to 'Xamarin.Forms.Controls.Issues')
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/GestureBubblingTests.cs211
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems1
2 files changed, 212 insertions, 0 deletions
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/GestureBubblingTests.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/GestureBubblingTests.cs
new file mode 100644
index 00000000..145fbf80
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/GestureBubblingTests.cs
@@ -0,0 +1,211 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.Forms.Internals;
+
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest.Queries;
+#endif
+
+namespace Xamarin.Forms.Controls.Issues
+{
+ // This is similar to the test for 35477, but tests all of the basic controls to make sure that they all exhibit
+ // the same behavior across all the platforms. The question is whether tapping a control inside of a frame
+ // will trigger the frame's tap gesture; for most controls it will not (the control itself absorbs the tap),
+ // but for non-interactive controls (box, frame, image, label) the gesture bubbles up to the container.
+
+ [Preserve(AllMembers = true)]
+ [Issue(IssueTracker.None, 00100100, "Verify that the tap gesture bubbling behavior is consistent across the platforms", PlatformAffected.All)]
+ public class GestureBubblingTests : TestNavigationPage
+ {
+ const string TargetAutomationId = "controlinsideofframe";
+ ContentPage _menu;
+
+#if UITEST
+ [Test, TestCaseSource(nameof(TestCases))]
+ public void VerifyTapBubbling(string menuItem, bool frameShouldRegisterTap)
+ {
+ var results = RunningApp.WaitForElement(q => q.Marked(menuItem));
+
+ if (results.Length > 1)
+ {
+ var rect = results.First(r => r.Class.Contains("Button")).Rect;
+
+ RunningApp.TapCoordinates(rect.CenterX, rect.CenterY);
+ }
+ else
+ {
+ RunningApp.Tap(q => q.Marked(menuItem));
+ }
+
+ // Find the start label
+ RunningApp.WaitForElement(q => q.Marked("Start"));
+
+ // Find the control we're testing
+ var result = RunningApp.WaitForElement(q => q.Marked(TargetAutomationId));
+ var target = result.First().Rect;
+
+ // Tap the control
+ var y = target.CenterY;
+ var x = target.CenterX;
+
+ // In theory we want to tap the center of the control. But Stepper lays out differently than the other controls,
+ // so we need to adjust for it until someone fixes it
+ if (menuItem == "Stepper")
+ {
+ y = target.Y + 5;
+ x = target.X + 5;
+ }
+
+ RunningApp.TapCoordinates(x, y);
+
+ if (menuItem == nameof(DatePicker) || menuItem == nameof(TimePicker))
+ {
+ // These controls show a pop-up which we have to cancel/done out of before we can continue
+#if __ANDROID__
+ var cancelButtonText = "Cancel";
+#elif __IOS__
+ var cancelButtonText = "Done";
+#else
+ var cancelButtonText = "X";
+#endif
+ RunningApp.WaitForElement(q => q.Marked(cancelButtonText));
+ RunningApp.Tap(q => q.Marked(cancelButtonText));
+ }
+
+ if (frameShouldRegisterTap)
+ {
+ RunningApp.WaitForElement(q => q.Marked("Frame was tapped"));
+ }
+ else
+ {
+ RunningApp.WaitForElement(q => q.Marked("Start"));
+ }
+ }
+#endif
+
+ ContentPage CreateTestPage(View view)
+ {
+ var instructions = new Label();
+
+ if (_controlsWhichShouldAllowTheTapToBubbleUp.Contains(view.GetType().Name))
+ {
+ instructions.Text =
+ "Tap the frame below. The label with the text 'No taps yet' should change its text to 'Frame was tapped'.";
+ }
+ else
+ {
+ instructions.Text =
+ "Tap the frame below. The label with the text 'No taps yet' should not change.";
+ }
+
+ var label = new Label { Text = "Start" };
+
+ var frame = new Frame { Content = new StackLayout { Children = { view } } };
+
+ var rec = new TapGestureRecognizer { NumberOfTapsRequired = 1 };
+ rec.Tapped += (s, e) => { label.Text = "Frame was tapped"; };
+ frame.GestureRecognizers.Add(rec);
+
+ var layout = new StackLayout();
+
+ layout.Children.Add(instructions);
+ layout.Children.Add(label);
+ layout.Children.Add(frame);
+
+ return new ContentPage { Content = layout };
+ }
+
+ Button MenuButton(string label, Func<View> view)
+ {
+ var button = new Button { Text = label };
+
+ var testView = view();
+ testView.AutomationId = TargetAutomationId;
+
+ button.Clicked += (sender, args) => PushAsync(CreateTestPage(testView));
+
+ return button;
+ }
+
+ // These controls should allow the tap gesture to bubble up to their container; everything else should absorb the gesture
+ readonly List<string> _controlsWhichShouldAllowTheTapToBubbleUp = new List<string>
+ {
+ nameof(Image),
+ nameof(Label),
+ nameof(BoxView),
+ nameof(Frame)
+ };
+
+ IEnumerable<object[]> TestCases
+ {
+ get
+ {
+ var layout = BuildMenu().Content as Layout;
+ var result =
+ from Layout element in layout.InternalChildren
+ from Button button in element.InternalChildren
+ let text = button.Text
+ select new object[]
+ {
+ text,
+ _controlsWhichShouldAllowTheTapToBubbleUp.Contains(text)
+ };
+
+ return result;
+ }
+ }
+
+ ContentPage BuildMenu()
+ {
+ if (_menu != null)
+ {
+ return _menu;
+ }
+
+ var layout = new Grid
+ {
+ VerticalOptions = LayoutOptions.Fill,
+ HorizontalOptions = LayoutOptions.Fill,
+ ColumnDefinitions = new ColumnDefinitionCollection { new ColumnDefinition(), new ColumnDefinition() }
+ };
+
+ var col1 = new StackLayout();
+ layout.Children.Add(col1);
+ Grid.SetColumn(col1, 0);
+
+ var col2 = new StackLayout();
+ layout.Children.Add(col2);
+ Grid.SetColumn(col2, 1);
+
+ col1.Children.Add(MenuButton(nameof(Image), () => new Image { Source = ImageSource.FromFile("oasis.jpg") }));
+ col1.Children.Add(MenuButton(nameof(Frame), () => new Frame { BackgroundColor = Color.DarkGoldenrod }));
+ col1.Children.Add(MenuButton(nameof(Entry), () => new Entry()));
+ col1.Children.Add(MenuButton(nameof(Editor), () => new Editor()));
+ col1.Children.Add(MenuButton(nameof(Button), () => new Button { Text = "Test" }));
+ col1.Children.Add(MenuButton(nameof(Label), () => new Label
+ {
+ LineBreakMode = LineBreakMode.WordWrap,
+ Text = "Lorem ipsum dolor sit amet"
+ }));
+ col1.Children.Add(MenuButton(nameof(SearchBar), () => new SearchBar()));
+
+ col2.Children.Add(MenuButton(nameof(DatePicker), () => new DatePicker()));
+ col2.Children.Add(MenuButton(nameof(TimePicker), () => new TimePicker()));
+ col2.Children.Add(MenuButton(nameof(Slider), () => new Slider()));
+ col2.Children.Add(MenuButton(nameof(Switch), () => new Switch()));
+ col2.Children.Add(MenuButton(nameof(Stepper), () => new Stepper()));
+ col2.Children.Add(MenuButton(nameof(BoxView), () => new BoxView { BackgroundColor = Color.DarkMagenta, WidthRequest = 100, HeightRequest = 100 }));
+
+ return new ContentPage { Content = layout };
+ }
+
+ protected override void Init()
+ {
+ PushAsync(BuildMenu());
+ }
+ }
+} \ 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 4369eee3..84d146ba 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
@@ -203,6 +203,7 @@
<DependentUpon>Bugzilla38416.xaml</DependentUpon>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)FailImageSource.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)GestureBubblingTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)InputTransparentTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)IsInvokeRequiredRaceCondition.cs" />
<Compile Include="$(MSBuildThisFileDirectory)IsPasswordToggleTest.cs" />