maui-linux/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issu.../Issue2894.cs

253 строки
6.4 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;
using System.Linq;
#if UITEST
using Xamarin.UITest;
using NUnit.Framework;
using Xamarin.Forms.Core.UITests;
#endif
namespace Xamarin.Forms.Controls.Issues
{
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Github, 2894, "Gesture Recognizers added to Span after it's been set to FormattedText don't work and can cause an NRE")]
#if UITEST
[NUnit.Framework.Category(UITestCategories.Gestures)]
#endif
public class Issue2894 : TestContentPage
{
Label label = null;
Label gestureLabel1 = null;
Label gestureLabel2 = null;
int i1 = 0;
int i2 = 0;
const string kGesture1 = "Sentence 1: ";
const string kGesture2 = "Sentence 2: ";
const string kClickSentence1 = "I will fire when clicked. ";
const string kClickSentence2 = "I should also fire when clicked.";
const string kClickSentenceAutomationId1 = "Spanning1";
const string kClickSentenceAutomationId2 = "Spanning2";
const string kLabelAutomationId = "kLabelAutomationId";
GestureRecognizer CreateRecognizer1() => new TapGestureRecognizer()
{
Command = new Command(() =>
{
i1++;
gestureLabel1.Text = $"{kGesture1}{i1}";
})
};
GestureRecognizer CreateRecognizer2() => new TapGestureRecognizer()
{
Command = new Command(() =>
{
i2++;
gestureLabel2.Text = $"{kGesture2}{i2}";
})
};
void AddRemoveSpan(bool includeRecognizers = true)
{
if (label.FormattedText != null)
{
label.FormattedText = null;
return;
}
FormattedString s = new FormattedString();
var span = new Span
{
Text = kClickSentence1,
FontAttributes = FontAttributes.Bold,
AutomationId = kClickSentenceAutomationId1
};
var span2 = new Span
{
Text = kClickSentence2,
FontAttributes = FontAttributes.Bold,
AutomationId = kClickSentenceAutomationId2
};
if (includeRecognizers)
span.GestureRecognizers.Add(CreateRecognizer1());
s.Spans.Add(span);
s.Spans.Add(span2);
label.FormattedText = s;
if (includeRecognizers)
span2.GestureRecognizers.Add(CreateRecognizer2());
}
Label GetLabel() =>
new Label()
{
HorizontalOptions = LayoutOptions.Center,
AutomationId = kLabelAutomationId
};
protected override void Init()
{
BindingContext = this;
label = GetLabel();
gestureLabel1 = new Label() { HorizontalOptions = LayoutOptions.Center };
gestureLabel2 = new Label() { HorizontalOptions = LayoutOptions.Center };
gestureLabel1.Text = $"{kGesture1}{i1}";
gestureLabel2.Text = $"{kGesture2}{i2}";
AddRemoveSpan();
StackLayout stackLayout = null;
stackLayout = new StackLayout()
{
Children =
{
label,
gestureLabel1,
gestureLabel2,
new Label(){Text = "Each sentence above has a separate Gesture Recognizer. Click each button below once then test that each Gesture Recognizer fires separately. If the sentence wraps make sure to click on the wrapped text as well."},
// test removing then adding span back
new Button()
{
Text = "Add and Remove Spans",
AutomationId = "TestSpan1",
Command = new Command(async () =>
{
if(label.FormattedText != null)
AddRemoveSpan();
await Task.Delay(100);
AddRemoveSpan();
})
},
// test removing and adding same span back
new Button()
{
Text = "Null FormattedText then set again",
AutomationId = "TestSpan2",
Command = new Command(async () =>
{
if(label.FormattedText == null)
AddRemoveSpan();
var span = label.FormattedText;
await Task.Delay(100);
label.FormattedText = null;
await Task.Delay(100);
label.FormattedText = span;
})
},
new Button()
{
Text = "Remove Gestures then add again",
AutomationId = "TestSpan3",
Command = new Command(async () =>
{
if(label.FormattedText == null)
AddRemoveSpan();
if(label.FormattedText.Spans[0].GestureRecognizers.Count > 0)
{
label.FormattedText.Spans[0].GestureRecognizers.Clear();
label.FormattedText.Spans[1].GestureRecognizers.Clear();
}
await Task.Delay(100);
label.FormattedText.Spans[0].GestureRecognizers.Add(CreateRecognizer1());
label.FormattedText.Spans[1].GestureRecognizers.Add(CreateRecognizer2());
})
},
new Button()
{
Text = "Add Gestures after rendering",
AutomationId = "TestSpan4",
Command = new Command(async () =>
{
stackLayout.Children.Remove(label);
await Task.Delay(50);
label = GetLabel();
stackLayout.Children.Insert(0, label);
await Task.Delay(50);
AddRemoveSpan(false);
await Task.Delay(50);
label.FormattedText.Spans[0].GestureRecognizers.Add(CreateRecognizer1());
label.FormattedText.Spans[1].GestureRecognizers.Add(CreateRecognizer2());
})
},
new Label()
{
Text = "This Button should remove all gestures"
},
new Button()
{
Text = "Remove All Gestures",
AutomationId = "TestSpan5",
Command = new Command(() =>
{
if(label.FormattedText == null)
return;
label.FormattedText.Spans[0].GestureRecognizers.Clear();
label.FormattedText.Spans[1].GestureRecognizers.Clear();
})
}
},
Padding = 40
};
Content = new ContentView()
{
Content = stackLayout
};
}
#if UITEST
[Test]
public void VariousSpanGesturePermutation()
{
RunningApp.WaitForElement($"{kGesture1}0");
RunningApp.WaitForElement($"{kGesture2}0");
var labelId = RunningApp.WaitForElement(kLabelAutomationId);
var target = labelId.First().Rect;
for (int i = 1; i < 5; i++)
{
RunningApp.Tap($"TestSpan{i}");
RunningApp.TapCoordinates(target.X + 5, target.Y + 5);
RunningApp.TapCoordinates(target.X + target.CenterX, target.Y + 2);
RunningApp.WaitForElement($"{kGesture1}{i}");
RunningApp.WaitForElement($"{kGesture2}{i}");
}
RunningApp.Tap($"TestSpan5");
RunningApp.TapCoordinates(target.X + 5, target.Y + 5);
RunningApp.TapCoordinates(target.X + target.CenterX, target.Y + 2);
RunningApp.WaitForElement($"{kGesture1}4");
RunningApp.WaitForElement($"{kGesture2}4");
}
#endif
}
}