Skip to content
This repository was archived by the owner on May 1, 2024. It is now read-only.

Commit fdb0dac

Browse files
jsuarezruizsamhoutshartezrmarinho
authored
[iOS] Fix issue using TapGesture (#11419) fixes #10623 fixes #12685 fixes #13020
* Added repro sample * Fixed the issue * Update Issue11050.xaml.cs * Updated issue 10626. Replaced Color by Brush. * Fixed build error * Fixed build error * Added Issue12685 test * Changes in text format * Fix rebase error Co-authored-by: Samantha Houts <samhouts@users.noreply.github.com> Co-authored-by: E.Z. Hart <hartez@gmail.com> Co-authored-by: Rui Marinho <me@ruimarinho.net>
1 parent c80a908 commit fdb0dac

File tree

4 files changed

+364
-2
lines changed

4 files changed

+364
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using Xamarin.Forms.CustomAttributes;
5+
using Xamarin.Forms.Internals;
6+
using Xamarin.Forms.Shapes;
7+
8+
#if UITEST
9+
using Xamarin.Forms.Core.UITests;
10+
using Xamarin.UITest;
11+
using NUnit.Framework;
12+
#endif
13+
14+
namespace Xamarin.Forms.Controls.Issues
15+
{
16+
#if UITEST
17+
[Category(UITestCategories.Shape)]
18+
#endif
19+
[Preserve(AllMembers = true)]
20+
[Issue(IssueTracker.Github, 10623, "Tap Gesture not working on iOS [Bug]", PlatformAffected.iOS)]
21+
public class Issue10623 : TestContentPage
22+
{
23+
public Issue10623()
24+
{
25+
Device.SetFlags(new List<string>(Device.Flags ?? new List<string>()) { "Shapes_Experimental" });
26+
27+
var layout = new StackLayout();
28+
29+
var instructions = new Label
30+
{
31+
Padding = 12,
32+
BackgroundColor = Color.Black,
33+
TextColor = Color.White,
34+
Text = "Tap the rating control. If you can modify the number of selected stars, the test has passed."
35+
};
36+
37+
var rating = new RatingControl
38+
{
39+
Size = 30,
40+
Max = 5,
41+
FillColor = Brush.Gold,
42+
StrokeColor = Brush.Silver,
43+
StrokeThickness = 2,
44+
HorizontalOptions = LayoutOptions.Center
45+
};
46+
47+
layout.Children.Add(instructions);
48+
layout.Children.Add(rating);
49+
50+
Content = layout;
51+
}
52+
53+
protected override void Init()
54+
{
55+
Title = "Issue 10623";
56+
}
57+
}
58+
59+
public class RatingControl : StackLayout
60+
{
61+
public RatingControl()
62+
{
63+
Orientation = StackOrientation.Horizontal;
64+
}
65+
66+
public static BindableProperty RatingProperty = BindableProperty.Create(nameof(Rating), typeof(double), typeof(RatingControl), 0.0, BindingMode.OneWay, propertyChanged: (bindable, newValue, oldValue) =>
67+
{
68+
var control = (RatingControl)bindable;
69+
70+
if (newValue != oldValue)
71+
{
72+
control.Draw();
73+
}
74+
});
75+
76+
readonly List<Point> _originalFullStarPoints = new List<Point>()
77+
{
78+
new Point(96,1.12977573),
79+
new Point(66.9427701,60.0061542),
80+
new Point(1.96882894,69.4474205),
81+
new Point(48.9844145,115.27629),
82+
new Point(37.8855403,179.987692),
83+
new Point(96,149.435112),
84+
new Point(154.11446,179.987692),
85+
new Point(143.015586,115.27629),
86+
new Point(190.031171,69.4474205),
87+
new Point(125.05723,60.0061542),
88+
new Point(96,1.12977573),
89+
};
90+
91+
readonly List<Point> _originalHalfStarPoints = new List<Point>()
92+
{
93+
new Point(96,1.12977573),
94+
new Point(66.9427701,60.0061542),
95+
new Point(1.96882894,69.4474205),
96+
new Point(48.9844145,115.27629),
97+
new Point(37.8855403,179.987692),
98+
new Point(96,149.435112),
99+
new Point(96,1.12977573)
100+
};
101+
102+
readonly PointCollection _fullStarPoints = new PointCollection();
103+
readonly PointCollection _halfStarPoints = new PointCollection();
104+
105+
double _ratio;
106+
107+
private void Draw()
108+
{
109+
Children.Clear();
110+
111+
var newRatio = Size / 200;
112+
113+
if (newRatio != _ratio)
114+
{
115+
_ratio = newRatio;
116+
117+
CalculatePoints(_fullStarPoints, _originalFullStarPoints);
118+
CalculatePoints(_halfStarPoints, _originalHalfStarPoints);
119+
}
120+
121+
122+
for (var i = 1; i <= Max; i++)
123+
{
124+
if (Rating >= i)
125+
{
126+
Children.Add(GetFullStar());
127+
}
128+
else if (Rating > i - 1)
129+
{
130+
Children.Add(GetHalfStar());
131+
}
132+
else
133+
{
134+
Children.Add(GetEmptyStar());
135+
}
136+
}
137+
138+
UpdateTapGestureRecognizers();
139+
}
140+
141+
private void CalculatePoints(PointCollection calculated, List<Point> original)
142+
{
143+
calculated.Clear();
144+
145+
foreach (var point in original)
146+
{
147+
var x = point.X * _ratio;
148+
var y = point.Y * _ratio;
149+
150+
var p = new Point(x, y);
151+
152+
calculated.Add(p);
153+
}
154+
}
155+
156+
private Polygon GetFullStar()
157+
{
158+
var fullStar = new Polygon()
159+
{
160+
Points = _fullStarPoints,
161+
Fill = FillColor,
162+
StrokeThickness = StrokeThickness,
163+
Stroke = StrokeColor
164+
};
165+
166+
return fullStar;
167+
}
168+
169+
private Grid GetHalfStar()
170+
{
171+
var grid = new Grid();
172+
173+
var halfStar = new Polygon()
174+
{
175+
Points = _halfStarPoints,
176+
Fill = _fillColor,
177+
Stroke = Brush.Transparent,
178+
StrokeThickness = 0,
179+
};
180+
181+
var emptyStar = new Polygon()
182+
{
183+
Points = _fullStarPoints,
184+
StrokeThickness = StrokeThickness,
185+
Stroke = StrokeColor
186+
};
187+
188+
grid.Children.Add(halfStar);
189+
grid.Children.Add(emptyStar);
190+
191+
return grid;
192+
}
193+
194+
private Polygon GetEmptyStar()
195+
{
196+
var emptyStar = new Polygon()
197+
{
198+
Points = _fullStarPoints,
199+
StrokeThickness = StrokeThickness,
200+
Stroke = StrokeColor
201+
};
202+
203+
return emptyStar;
204+
}
205+
206+
private void Set<T>(ref T field, T newValue)
207+
{
208+
if (!EqualityComparer<T>.Default.Equals(field, newValue))
209+
{
210+
field = newValue;
211+
Draw();
212+
}
213+
}
214+
215+
public double Rating
216+
{
217+
get => (double)GetValue(RatingProperty);
218+
set => SetValue(RatingProperty, value);
219+
}
220+
221+
int _max = 5;
222+
public int Max
223+
{
224+
get => _max;
225+
set => Set(ref _max, value);
226+
}
227+
228+
229+
Brush _fillColor = Brush.Yellow;
230+
public Brush FillColor
231+
{
232+
get => _fillColor;
233+
set => Set(ref _fillColor, value);
234+
}
235+
236+
Brush _strokeColor = Brush.Black;
237+
public Brush StrokeColor
238+
{
239+
get => _strokeColor;
240+
set => Set(ref _strokeColor, value);
241+
}
242+
243+
double _strokeThickness = 0;
244+
public double StrokeThickness
245+
{
246+
get => _strokeThickness;
247+
set => Set(ref _strokeThickness, value);
248+
}
249+
250+
double _size = 50;
251+
public double Size
252+
{
253+
get => _size;
254+
set => Set(ref _size, value);
255+
}
256+
257+
private void UpdateTapGestureRecognizers()
258+
{
259+
foreach (var star in Children)
260+
{
261+
if (!star.GestureRecognizers.Any())
262+
{
263+
var recognizer = new TapGestureRecognizer();
264+
recognizer.Tapped += TapGestureRecognizer_Tapped;
265+
star.GestureRecognizers.Add(recognizer);
266+
}
267+
}
268+
}
269+
270+
private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
271+
{
272+
var star = (View)sender;
273+
274+
var index = Children.IndexOf(star);
275+
276+
Rating = index + 1;
277+
}
278+
}
279+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
using System;
2+
using System.ComponentModel;
3+
using System.Windows.Input;
4+
using Xamarin.Forms.CustomAttributes;
5+
using Xamarin.Forms.Internals;
6+
using Xamarin.Forms.Shapes;
7+
8+
#if UITEST
9+
using Xamarin.UITest;
10+
using NUnit.Framework;
11+
using Xamarin.Forms.Core.UITests;
12+
#endif
13+
14+
namespace Xamarin.Forms.Controls.Issues
15+
{
16+
[Preserve(AllMembers = true)]
17+
[Issue(IssueTracker.Github, 12685, "[iOs][Bug] TapGestureRecognizer in Path does not work on iOS", PlatformAffected.iOS)]
18+
#if UITEST
19+
[NUnit.Framework.Category(Core.UITests.UITestCategories.Github10000)]
20+
[NUnit.Framework.Category(UITestCategories.Shape)]
21+
#endif
22+
public partial class Issue12685 : TestContentPage
23+
{
24+
const string ResetStatus = "Path touch event not fired, touch path above.";
25+
const string ClickedStatus = "Path was clicked, click reset button to start over.";
26+
27+
protected override void Init()
28+
{
29+
var layout = new StackLayout();
30+
var statusLabel = new Label
31+
{
32+
AutomationId = "LabelValue",
33+
Text = ResetStatus,
34+
};
35+
36+
var lgb = new LinearGradientBrush();
37+
lgb.GradientStops.Add(new GradientStop(Color.White, 0));
38+
lgb.GradientStops.Add(new GradientStop(Color.Orange, 1));
39+
40+
var pathGeometry = new PathGeometry();
41+
PathFigureCollectionConverter.ParseStringToPathFigureCollection(pathGeometry.Figures, "M0,0 V300 H300 V-300 Z");
42+
43+
var path = new Path
44+
{
45+
Data = pathGeometry,
46+
Fill = lgb
47+
};
48+
49+
var touch = new TapGestureRecognizer
50+
{
51+
Command = new Command(_ => statusLabel.Text = ClickedStatus),
52+
};
53+
path.GestureRecognizers.Add(touch);
54+
55+
var resetButton = new Button
56+
{
57+
Text = "Reset",
58+
Command = new Command(_ => statusLabel.Text = ResetStatus),
59+
};
60+
61+
layout.Children.Add(path);
62+
layout.Children.Add(statusLabel);
63+
layout.Children.Add(resetButton);
64+
65+
Content = layout;
66+
}
67+
68+
#if UITEST
69+
[Test]
70+
public void ShapesPathReceiveGestureRecognizers()
71+
{
72+
var testLabel = RunningApp.WaitForFirstElement("LabelValue");
73+
Assert.AreEqual(ResetStatus, testLabel.ReadText());
74+
var pathRect = testLabel.Rect;
75+
RunningApp.TapCoordinates(pathRect.X + 100, pathRect.Y-100);
76+
Assert.AreEqual(ClickedStatus, RunningApp.WaitForFirstElement("LabelValue").ReadText());
77+
}
78+
#endif
79+
}
80+
}

Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems

+3-1
Original file line numberDiff line numberDiff line change
@@ -1633,7 +1633,8 @@
16331633
<Compile Include="$(MSBuildThisFileDirectory)Issue11938.xaml.cs">
16341634
<DependentUpon>Issue11938.xaml</DependentUpon>
16351635
</Compile>
1636-
<Compile Include="$(MSBuildThisFileDirectory)Issue11496.xaml.cs">
1636+
<Compile Include="$(MSBuildThisFileDirectory)Issue10623.cs" />
1637+
<Compile Include="$(MSBuildThisFileDirectory)Issue11496.xaml.cs" >
16371638
<DependentUpon>Issue11496.xaml</DependentUpon>
16381639
</Compile>
16391640
<Compile Include="$(MSBuildThisFileDirectory)Issue11209.xaml.cs">
@@ -1653,6 +1654,7 @@
16531654
<Compile Include="$(MSBuildThisFileDirectory)Issue8988.cs" />
16541655
<Compile Include="$(MSBuildThisFileDirectory)Issue12084.xaml.cs" />
16551656
<Compile Include="$(MSBuildThisFileDirectory)Issue12512.cs" />
1657+
<Compile Include="$(MSBuildThisFileDirectory)Issue12685.cs" />
16561658
<Compile Include="$(MSBuildThisFileDirectory)Issue12642.cs" />
16571659
</ItemGroup>
16581660
<ItemGroup>

Xamarin.Forms.Platform.iOS/EventTracker.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -667,7 +667,8 @@ bool ShouldReceiveTouch(UIGestureRecognizer recognizer, UITouch touch)
667667
return false;
668668
}
669669

670-
if (touch.View.IsDescendantOfView(_renderer.NativeView) && touch.View.GestureRecognizers?.Length > 0)
670+
if (touch.View.IsDescendantOfView(_renderer.NativeView) &&
671+
(touch.View.GestureRecognizers?.Length > 0 || _renderer.NativeView.GestureRecognizers?.Length > 0))
671672
{
672673
return true;
673674
}

0 commit comments

Comments
 (0)