diff --git a/src/Controls/tests/TestCases.Android.Tests/snapshots/android/VerifyCheckBoxCheckedState.png b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/VerifyCheckBoxCheckedState.png new file mode 100644 index 000000000000..281fbe55b00a Binary files /dev/null and b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/VerifyCheckBoxCheckedState.png differ diff --git a/src/Controls/tests/TestCases.Android.Tests/snapshots/android/VerifyCheckBoxUnCheckedState.png b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/VerifyCheckBoxUnCheckedState.png new file mode 100644 index 000000000000..4878bc33c2ef Binary files /dev/null and b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/VerifyCheckBoxUnCheckedState.png differ diff --git a/src/Controls/tests/TestCases.Android.Tests/snapshots/android/VerifySwipeViewApperance.png b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/VerifySwipeViewApperance.png new file mode 100644 index 000000000000..79b15fa8781b Binary files /dev/null and b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/VerifySwipeViewApperance.png differ diff --git a/src/Controls/tests/TestCases.Android.Tests/snapshots/android/VerifyTimePickerApperance.png b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/VerifyTimePickerApperance.png new file mode 100644 index 000000000000..a27f92ec57a4 Binary files /dev/null and b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/VerifyTimePickerApperance.png differ diff --git a/src/Controls/tests/TestCases.HostApp/Issues/CheckBoxUITest.cs b/src/Controls/tests/TestCases.HostApp/Issues/CheckBoxUITest.cs new file mode 100644 index 000000000000..c72c65cc85f1 --- /dev/null +++ b/src/Controls/tests/TestCases.HostApp/Issues/CheckBoxUITest.cs @@ -0,0 +1,43 @@ +namespace Maui.Controls.Sample.Issues; + +[Issue(IssueTracker.None, 26593, "CheckBox UI Test", PlatformAffected.iOS)] +public partial class CheckBoxUITestSample : ContentPage +{ + public CheckBoxUITestSample() + { + Grid grid = new Grid() + { + ColumnDefinitions = new ColumnDefinitionCollection + { + new ColumnDefinition(), + new ColumnDefinition() + } + }; + + Label label = new Label + { + Text = "CheckBox", + VerticalOptions = LayoutOptions.Center, + HorizontalOptions = LayoutOptions.End, + AutomationId = "Label" + }; + + CheckBox checkBox = new CheckBox + { + IsChecked = true, + Color = Colors.Red, + VerticalOptions = LayoutOptions.Center, + HorizontalOptions = LayoutOptions.Center, + AutomationId = "CheckBox" + }; + + checkBox.CheckedChanged += (s, e) => + { + label.Text = $"CheckBox is {(checkBox.IsChecked ? "Checked" : "Unchecked")}"; + }; + + grid.AddChild(label, 0, 0); + grid.AddChild(checkBox, 1, 0); + Content = grid; + } +} \ No newline at end of file diff --git a/src/Controls/tests/TestCases.HostApp/Issues/SwipeViewUITest.cs b/src/Controls/tests/TestCases.HostApp/Issues/SwipeViewUITest.cs new file mode 100644 index 000000000000..2d22c54ff27a --- /dev/null +++ b/src/Controls/tests/TestCases.HostApp/Issues/SwipeViewUITest.cs @@ -0,0 +1,39 @@ +namespace Maui.Controls.Sample.Issues; + +[Issue(IssueTracker.None, 26593, "SwipeView UI Test", PlatformAffected.iOS)] +public partial class SwipeViewUITest : ContentPage +{ + public SwipeViewUITest() + { + + SwipeItem favoriteSwipeItem = new SwipeItem + { + Text = "Coffee", + IconImageSource = "coffee.png", + BackgroundColor = Colors.Brown + }; + + // SwipeView content + Grid grid = new Grid + { + HeightRequest = 60, + BackgroundColor = Colors.LightGray + }; + grid.Add(new Label + { + Text = "Swipe right", + AutomationId = "SwipeRight", + HorizontalOptions = LayoutOptions.Center, + VerticalOptions = LayoutOptions.Center + }); + + SwipeView swipeView = new SwipeView + { + RightItems = new SwipeItems { favoriteSwipeItem }, + Content = grid + }; + + Content = swipeView; + + } +} \ No newline at end of file diff --git a/src/Controls/tests/TestCases.HostApp/Issues/TimePickerUITest.cs b/src/Controls/tests/TestCases.HostApp/Issues/TimePickerUITest.cs new file mode 100644 index 000000000000..39ab8e0fc064 --- /dev/null +++ b/src/Controls/tests/TestCases.HostApp/Issues/TimePickerUITest.cs @@ -0,0 +1,20 @@ +namespace Maui.Controls.Sample.Issues; + +[Issue(IssueTracker.None, 26593, "TimePicker UI Test", PlatformAffected.iOS)] +public partial class TimePickerUITest : ContentPage +{ + public TimePickerUITest() + { + Grid grid = new Grid(); + + TimePicker timePicker = new TimePicker + { + Time = new TimeSpan(4, 14, 23), + Format = "hh:mm:ss", + AutomationId = "TimePicker" + }; + + grid.Children.Add(timePicker); + Content = grid; + } +} \ No newline at end of file diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/CheckBoxUITest.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/CheckBoxUITest.cs new file mode 100644 index 000000000000..58dffb11910d --- /dev/null +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/CheckBoxUITest.cs @@ -0,0 +1,35 @@ +#if TEST_FAILS_ON_CATALYST // On Catalyst, the CheckBox was not able to be tapped in the CI. +using NUnit.Framework; +using UITest.Appium; +using UITest.Core; + +namespace Microsoft.Maui.TestCases.Tests.Issues +{ + public class CheckBoxUITest : _IssuesUITest + { + public override string Issue => "CheckBox UI Test"; + + public CheckBoxUITest(TestDevice device) + : base(device) + { } + + [Test] + [Category(UITestCategories.CheckBox), Order(1)] + public void VerifyCheckBoxUnCheckedState() + { + App.WaitForElement("CheckBox"); + App.Tap("CheckBox"); + VerifyScreenshot(); + } + + [Test] + [Category(UITestCategories.CheckBox), Order(2)] + public void VerifyCheckBoxCheckedState() + { + App.WaitForElement("CheckBox"); + App.Tap("CheckBox"); + VerifyScreenshot(); + } + } +} +#endif \ No newline at end of file diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/SwipeViewUITest.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/SwipeViewUITest.cs new file mode 100644 index 000000000000..54c538d42b8b --- /dev/null +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/SwipeViewUITest.cs @@ -0,0 +1,28 @@ +#if ANDROID || IOS +using NUnit.Framework; +using UITest.Appium; +using UITest.Core; + +namespace Microsoft.Maui.TestCases.Tests.Issues +{ + public class SwipeViewUITest : _IssuesUITest + { + public override string Issue => "SwipeView UI Test"; + + public SwipeViewUITest(TestDevice device) + : base(device) + { } + + [Test] + [Category(UITestCategories.SwipeView)] + public void VerifySwipeViewApperance() + { + var rect = App.WaitForElement("SwipeRight").GetRect(); + var centerX = rect.X + rect.Width / 2; + var centerY = rect.Y + rect.Height / 2; + App.DragCoordinates(centerX, centerY, centerX - 200, centerY); + VerifyScreenshot(); + } + } +} +#endif diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/TimePickerUITest.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/TimePickerUITest.cs new file mode 100644 index 000000000000..0656ff450a79 --- /dev/null +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/TimePickerUITest.cs @@ -0,0 +1,26 @@ +#if TEST_FAILS_ON_CATALYST // TimePicker not opens the dialog, issue: https://github.com/dotnet/maui/issues/10827 +using NUnit.Framework; +using UITest.Appium; +using UITest.Core; + +namespace Microsoft.Maui.TestCases.Tests.Issues +{ + public class TimePickerUITest : _IssuesUITest + { + public override string Issue => "TimePicker UI Test"; + + public TimePickerUITest(TestDevice device) + : base(device) + { } + + [Test] + [Category(UITestCategories.TimePicker)] + public void VerifyTimePickerApperance() + { + App.WaitForElement("TimePicker"); + App.Tap("TimePicker"); + VerifyScreenshot(); + } + } +} +#endif diff --git a/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/VerifyCheckBoxCheckedState.png b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/VerifyCheckBoxCheckedState.png new file mode 100644 index 000000000000..0eba3e70d6a7 Binary files /dev/null and b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/VerifyCheckBoxCheckedState.png differ diff --git a/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/VerifyCheckBoxUnCheckedState.png b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/VerifyCheckBoxUnCheckedState.png new file mode 100644 index 000000000000..85a3ac1d898b Binary files /dev/null and b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/VerifyCheckBoxUnCheckedState.png differ diff --git a/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/VerifyTimePickerApperance.png b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/VerifyTimePickerApperance.png new file mode 100644 index 000000000000..297ab50ff836 Binary files /dev/null and b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/VerifyTimePickerApperance.png differ diff --git a/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/VerifyCheckBoxCheckedState.png b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/VerifyCheckBoxCheckedState.png new file mode 100644 index 000000000000..c9cf0db13aa9 Binary files /dev/null and b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/VerifyCheckBoxCheckedState.png differ diff --git a/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/VerifyCheckBoxUnCheckedState.png b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/VerifyCheckBoxUnCheckedState.png new file mode 100644 index 000000000000..8df3ac543cb1 Binary files /dev/null and b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/VerifyCheckBoxUnCheckedState.png differ diff --git a/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/VerifySwipeViewApperance.png b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/VerifySwipeViewApperance.png new file mode 100644 index 000000000000..a30e162afb0c Binary files /dev/null and b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/VerifySwipeViewApperance.png differ diff --git a/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/VerifyTimePickerApperance.png b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/VerifyTimePickerApperance.png new file mode 100644 index 000000000000..2a61deb1989f Binary files /dev/null and b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/VerifyTimePickerApperance.png differ diff --git a/src/Core/src/Handlers/SwipeItemMenuItem/SwipeItemMenuItemHandler.iOS.cs b/src/Core/src/Handlers/SwipeItemMenuItem/SwipeItemMenuItemHandler.iOS.cs index 7b6763267fe6..e2938f46bfa9 100644 --- a/src/Core/src/Handlers/SwipeItemMenuItem/SwipeItemMenuItemHandler.iOS.cs +++ b/src/Core/src/Handlers/SwipeItemMenuItem/SwipeItemMenuItemHandler.iOS.cs @@ -142,12 +142,39 @@ static UIImage MaxResizeSwipeItemIconImage(UIImage sourceImage, nfloat maxWidth, var width = maxResizeFactor * sourceSize.Width; var height = maxResizeFactor * sourceSize.Height; - UIGraphics.BeginImageContextWithOptions(new CGSize((nfloat)width, (nfloat)height), false, 0); - sourceImage.Draw(new CGRect(0, 0, (nfloat)width, (nfloat)height)); - var resultImage = UIGraphics.GetImageFromCurrentImageContext(); - UIGraphics.EndImageContext(); + if (!OperatingSystem.IsIOSVersionAtLeast(17)) + { + UIGraphics.BeginImageContextWithOptions(new CGSize((nfloat)width, (nfloat)height), false, 0); + sourceImage.Draw(new CGRect(0, 0, (nfloat)width, (nfloat)height)); + var resultImage = UIGraphics.GetImageFromCurrentImageContext(); + UIGraphics.EndImageContext(); + + return resultImage; + } + + var format = new UIGraphicsImageRendererFormat + { + Opaque = false, + Scale = 0 + }; - return resultImage; + using (var renderer = new UIGraphicsImageRenderer(new CGSize(width, height), format)) + { + var resultImage = renderer.CreateImage((UIGraphicsImageRendererContext imageContext) => + { + var cgcontext = imageContext.CGContext; + + // The image is drawn upside down because Core Graphics uses a bottom-left origin, + // whereas UIKit uses a top-left origin. Adjust the coordinate system to align with UIKit's top-left origin. + cgcontext.TranslateCTM(0, (nfloat)height); + cgcontext.ScaleCTM(1, -1); + cgcontext.DrawImage(new CGRect(0, 0, (nfloat)width, (nfloat)height), sourceImage.CGImage); + cgcontext.ScaleCTM(1, -1); + cgcontext.TranslateCTM(0, -(nfloat)height); + }); + + return resultImage; + } } } diff --git a/src/Core/src/Platform/iOS/MauiCheckBox.cs b/src/Core/src/Platform/iOS/MauiCheckBox.cs index a5ec9406d207..790f9ec30693 100644 --- a/src/Core/src/Platform/iOS/MauiCheckBox.cs +++ b/src/Core/src/Platform/iOS/MauiCheckBox.cs @@ -177,10 +177,17 @@ static void DrawCheckMark(UIBezierPath path) UIImage CreateCheckBox(UIImage? check) { - UIGraphics.BeginImageContextWithOptions(new CGSize(DefaultSize, DefaultSize), false, 0); - var context = UIGraphics.GetCurrentContext(); - context.SaveState(); + var renderer = new UIGraphicsImageRenderer(new CGSize(DefaultSize, DefaultSize)); + var image = renderer.CreateImage((UIGraphicsImageRendererContext ctx) => + { + var context = ctx.CGContext; + RenderCheckMark(context, check); + }); + return image; + } + void RenderCheckMark(CGContext context, UIImage? check) + { var checkedColor = CheckBoxTintUIColor; if (checkedColor != null) @@ -203,18 +210,21 @@ UIImage CreateCheckBox(UIImage? check) boxPath.Fill(); check.Draw(new CGPoint(0, 0), CGBlendMode.DestinationOut, 1); } - - context.RestoreState(); - var img = UIGraphics.GetImageFromCurrentImageContext(); - UIGraphics.EndImageContext(); - - return img; } static UIImage CreateCheckMark() { - UIGraphics.BeginImageContextWithOptions(new CGSize(DefaultSize, DefaultSize), false, 0); - var context = UIGraphics.GetCurrentContext(); + using var renderer = new UIGraphicsImageRenderer(new CGSize(DefaultSize, DefaultSize)); + var image = renderer.CreateImage((UIGraphicsImageRendererContext ctx) => + { + var context = ctx.CGContext; + RenderCheckMark(context); + }); + return image; + } + + static void RenderCheckMark(CGContext context) + { context.SaveState(); var vPadding = LineWidth / 2; @@ -230,10 +240,6 @@ static UIImage CreateCheckMark() checkPath.Stroke(); context.RestoreState(); - var img = UIGraphics.GetImageFromCurrentImageContext(); - UIGraphics.EndImageContext(); - - return img; } public override CGSize SizeThatFits(CGSize size) diff --git a/src/Core/src/Platform/iOS/MauiTimePicker.cs b/src/Core/src/Platform/iOS/MauiTimePicker.cs index e5cdbfa34c6a..701065ab0e20 100644 --- a/src/Core/src/Platform/iOS/MauiTimePicker.cs +++ b/src/Core/src/Platform/iOS/MauiTimePicker.cs @@ -25,7 +25,7 @@ public MauiTimePicker() _proxy = new(dateSelected); #endif - if (OperatingSystem.IsIOSVersionAtLeast(14)) + if (OperatingSystem.IsIOSVersionAtLeast(13, 4) || OperatingSystem.IsMacCatalyst()) { _picker.PreferredDatePickerStyle = UIDatePickerStyle.Wheels; }