diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml
index 7ce8893aba83..a12ed6362301 100644
--- a/.github/ISSUE_TEMPLATE/bug-report.yml
+++ b/.github/ISSUE_TEMPLATE/bug-report.yml
@@ -172,4 +172,4 @@ body:
- type: markdown
attributes:
value: |
- By opening the issue you agree to follow this project's [Code of Conduct](https://github.com/dotnet/maui/blob/main/.github/CODE_OF_CONDUCT.md)
+ By opening the issue you agree to follow this project's [Code of Conduct](https://github.com/dotnet/maui/blob/main/.github/CODE_OF_CONDUCT.md)
\ No newline at end of file
diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
index 7fe404670d4e..6545e1234b7d 100644
--- a/.github/copilot-instructions.md
+++ b/.github/copilot-instructions.md
@@ -273,4 +273,4 @@ Always put that at the top, without the block quotes. Without it, the users will
---
-**Note for Future Updates:** This document should be expanded as new development patterns, tools, or workflows are discovered. Add sections for specific scenarios, debugging techniques, or tooling as they become relevant to the development process.
+**Note for Future Updates:** This document should be expanded as new development patterns, tools, or workflows are discovered. Add sections for specific scenarios, debugging techniques, or tooling as they become relevant to the development process.
\ No newline at end of file
diff --git a/eng/pipelines/common/apiscan.yml b/eng/pipelines/common/apiscan.yml
index 97d9afcf294f..1e47db1d6c77 100644
--- a/eng/pipelines/common/apiscan.yml
+++ b/eng/pipelines/common/apiscan.yml
@@ -24,4 +24,3 @@ stages:
apiScanSoftwareVersionNum: ${{ parameters.softwareVersion }}
apiScanAuthConnectionString: 'runAs=App;AppId=$(ApiScanClientId)'
tsaUploadEnabled: ${{ parameters.tsaUploadEnabled }}
-
diff --git a/eng/pipelines/maui-release-internal.yml b/eng/pipelines/maui-release-internal.yml
index c44a8b34e6e2..6613e43084cc 100644
--- a/eng/pipelines/maui-release-internal.yml
+++ b/eng/pipelines/maui-release-internal.yml
@@ -288,4 +288,4 @@ extends:
$(Build.SourcesDirectory)\eng\scripts\push_nuget_org.ps1 -ApiKey "$(pat--nuget--xamarinc--push--wildcard)" -FeedUrl "${{ parameters.feedUrl }}" -NuGetSearchPath "$(Build.StagingDirectory)\nupkgs\shipping\packages\*" -NuGetIncludeFilters "*Manifest*.nupkg;${{ parameters.nugetIncludeFilters }}" -NuGetExcludeFilters "${{ parameters.nugetExcludeFilters }}"
displayName: Push workload manifests to NuGet.org
env:
- PUSH_PACKAGES: ${{ parameters.pushPackages }}
+ PUSH_PACKAGES: ${{ parameters.pushPackages }}
\ No newline at end of file
diff --git a/src/Controls/src/Core/Button/Button.iOS.cs b/src/Controls/src/Core/Button/Button.iOS.cs
index 863c2b0d0ff6..c710d5a2a8de 100644
--- a/src/Controls/src/Core/Button/Button.iOS.cs
+++ b/src/Controls/src/Core/Button/Button.iOS.cs
@@ -6,6 +6,7 @@
using Microsoft.Extensions.Logging;
using Microsoft.Maui.Controls.Platform;
using Microsoft.Maui.Graphics;
+using Microsoft.Maui.Graphics.Platform;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Layouts;
using UIKit;
@@ -393,7 +394,7 @@ bool ResizeImageIfNecessary(UIButton platformButton, Button button, UIImage imag
// if the image is too large then we will size it smaller
if (currentImageHeight - availableHeight > buffer || currentImageWidth - availableWidth > buffer)
{
- image = ResizeImageSource(image, availableWidth, availableHeight, _originalImageSize);
+ image = image.ResizeImageSource(availableWidth, availableHeight, _originalImageSize);
}
// if the image is already sized down but now has more space, we will size it up no more than the original image size
else if (availableHeight - additionalVerticalSpace - currentImageHeight > buffer
@@ -401,7 +402,7 @@ bool ResizeImageIfNecessary(UIButton platformButton, Button button, UIImage imag
&& currentImageHeight != _originalImageSize.Height
&& currentImageWidth != _originalImageSize.Width)
{
- image = ResizeImageSource(image, (nfloat)widthConstraint - additionalHorizontalSpace, (nfloat)heightConstraint - additionalVerticalSpace, _originalImageSize, true);
+ image = image.ResizeImageSource((nfloat)widthConstraint - additionalHorizontalSpace, (nfloat)heightConstraint - additionalVerticalSpace, _originalImageSize, true);
}
else
{
@@ -422,33 +423,6 @@ bool ResizeImageIfNecessary(UIButton platformButton, Button button, UIImage imag
return false;
}
- ///
- /// Resize the image to fit within the constraints.
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- static UIImage ResizeImageSource(UIImage sourceImage, nfloat maxWidth, nfloat maxHeight, CGSize originalImageSize, bool shouldScaleUp = false)
- {
- if (sourceImage is null || sourceImage.CGImage is null)
- return null;
-
- maxWidth = (nfloat)Math.Min(maxWidth, originalImageSize.Width);
- maxHeight = (nfloat)Math.Min(maxHeight, originalImageSize.Height);
-
- var sourceSize = sourceImage.Size;
-
- float maxResizeFactor = (float)Math.Min(maxWidth / sourceSize.Width, maxHeight / sourceSize.Height);
-
- if (maxResizeFactor > 1 && !shouldScaleUp)
- return sourceImage;
-
- return UIImage.FromImage(sourceImage.CGImage, sourceImage.CurrentScale / maxResizeFactor, sourceImage.Orientation);
- }
-
public static void MapText(ButtonHandler handler, Button button) =>
MapText((IButtonHandler)handler, button);
diff --git a/src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs
index f1e2ac75a77e..5371d80e4c09 100644
--- a/src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs
+++ b/src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs
@@ -11,6 +11,7 @@
using Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific;
using Microsoft.Maui.Devices;
using Microsoft.Maui.Graphics;
+using Microsoft.Maui.Graphics.Platform;
using Microsoft.Maui.Platform;
using ObjCRuntime;
using UIKit;
@@ -972,12 +973,21 @@ internal static void SetFlyoutLeftBarButton(UIViewController containerController
return;
}
-
FlyoutPage.Flyout.IconImageSource.LoadImage(FlyoutPage.FindMauiContext(), result =>
{
var icon = result?.Value;
- if (icon != null)
- {
+ var originalImageSize = icon?.Size ?? CGSize.Empty;
+ // Referred from the default hamburger size
+ var defaultIconHeight = 23f;
+ var defaultIconWidth = 23f;
+ var buffer = 0.1;
+ // if the image is bigger than the default available size, resize it
+ if (icon is not null)
+ {
+ if (originalImageSize.Height - defaultIconHeight > buffer || originalImageSize.Width - defaultIconWidth > buffer)
+ {
+ icon = icon.ResizeImageSource(defaultIconWidth, defaultIconHeight, originalImageSize);
+ }
try
{
containerController.NavigationItem.LeftBarButtonItem = new UIBarButtonItem(icon, UIBarButtonItemStyle.Plain, OnItemTapped);
diff --git a/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellPageRendererTracker.cs b/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellPageRendererTracker.cs
index 9ad9ad971baf..d5b96f34e0cb 100644
--- a/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellPageRendererTracker.cs
+++ b/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellPageRendererTracker.cs
@@ -4,6 +4,7 @@
using System.Collections.Specialized;
using System.ComponentModel;
using System.Runtime.Versioning;
+using Microsoft.Maui.Graphics.Platform;
using System.Windows.Input;
using CoreGraphics;
using Foundation;
@@ -415,9 +416,20 @@ void UpdateLeftToolbarItems()
UIImage? icon = null;
- if (image != null)
+ if (image is not null)
{
icon = result?.Value;
+ var originalImageSize = icon?.Size ?? CGSize.Empty;
+ // Referred from the default hamburger size
+ var defaultIconHeight = 23f;
+ var defaultIconWidth = 23f;
+ var buffer = 0.1;
+ // if the image is bigger than the default available size, resize it
+
+ if (icon is not null && originalImageSize.Height - defaultIconHeight > buffer || originalImageSize.Width - defaultIconWidth > buffer)
+ {
+ icon = icon.ResizeImageSource(defaultIconWidth, defaultIconHeight, originalImageSize);
+ }
}
else if (String.IsNullOrWhiteSpace(text) && IsRootPage && _flyoutBehavior == FlyoutBehavior.Flyout)
{
diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue25920.xaml b/src/Controls/tests/TestCases.HostApp/Issues/Issue25920.xaml
new file mode 100644
index 000000000000..4cf48c5bd16b
--- /dev/null
+++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue25920.xaml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue25920.xaml.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue25920.xaml.cs
new file mode 100644
index 000000000000..423cf59f853d
--- /dev/null
+++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue25920.xaml.cs
@@ -0,0 +1,14 @@
+using System;
+using Microsoft.Maui.Controls.Internals;
+
+namespace Maui.Controls.Sample.Issues
+{
+ [Issue(IssueTracker.Github, 25920, ".NET MAUI set AppShell custom FlyoutIcon display problem", PlatformAffected.iOS | PlatformAffected.Android)]
+ public partial class Issue25920: Shell
+ {
+ public Issue25920()
+ {
+ InitializeComponent();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue29092Flyout.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue29092Flyout.cs
new file mode 100644
index 000000000000..eb14b6bfb326
--- /dev/null
+++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue29092Flyout.cs
@@ -0,0 +1,20 @@
+namespace Maui.Controls.Sample.Issues;
+
+[Issue(IssueTracker.Github, "29092Flyout", "Flyout - Auto Resize chrome icons on iOS to make it more consistent with other platforms - hamburger icon", PlatformAffected.iOS)]
+public partial class Issue29092Flyout : FlyoutPage
+{
+ public Issue29092Flyout()
+ {
+ Flyout = new ContentPage
+ {
+ IconImageSource = "groceries.png",
+ Title = "Flyout"
+ };
+
+ Detail = new NavigationPage(new ContentPage
+ {
+ Title = "Title",
+ Content = new Label() { Text = "Hello, World!", AutomationId = "HelloWorldLabel", },
+ });
+ }
+}
\ No newline at end of file
diff --git a/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/FlyoutIconShouldAutoscale.png b/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/FlyoutIconShouldAutoscale.png
new file mode 100644
index 000000000000..73fe8cde6b9f
Binary files /dev/null and b/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/FlyoutIconShouldAutoscale.png differ
diff --git a/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/ForegroundColorShouldbeSetandCustomIconAlignedProperly.png b/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/ForegroundColorShouldbeSetandCustomIconAlignedProperly.png
new file mode 100644
index 000000000000..da9747f91aa2
Binary files /dev/null and b/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/ForegroundColorShouldbeSetandCustomIconAlignedProperly.png differ
diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue25920.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue25920.cs
new file mode 100644
index 000000000000..86ca7f57fc14
--- /dev/null
+++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue25920.cs
@@ -0,0 +1,28 @@
+#if TEST_FAILS_ON_WINDOWS && TEST_FAILS_ON_ANDROID
+// https://github.com/dotnet/maui/issues/26148
+// In Windows, the foreground color is not applied to the custom icon, so as of now, the test is not applicable for Windows.
+// https://github.com/dotnet/maui/pull/27502
+// For Android, we have separate PR to fix the issue, so the test is not applicable for Android.
+using NUnit.Framework;
+using UITest.Appium;
+using UITest.Core;
+
+namespace Microsoft.Maui.TestCases.Tests.Issues
+{
+ public class Issue25920 : _IssuesUITest
+ {
+ public Issue25920(TestDevice device) : base(device) { }
+
+ public override string Issue => ".NET MAUI set AppShell custom FlyoutIcon display problem";
+
+ [Test]
+ [Category(UITestCategories.Shell)]
+ public void ForegroundColorShouldbeSetandCustomIconAlignedProperly()
+ {
+ App.WaitForElement("Label");
+
+ VerifyScreenshot();
+ }
+ }
+}
+#endif
\ No newline at end of file
diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue29092Flyout.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue29092Flyout.cs
new file mode 100644
index 000000000000..7ce0e5cc6a87
--- /dev/null
+++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue29092Flyout.cs
@@ -0,0 +1,27 @@
+#if TEST_FAILS_ON_ANDROID && TEST_FAILS_ON_WINDOWS
+//IconImageSource is not properly updated in Android and Windows, so the test is not applicable for these platforms.
+//https://github.com/dotnet/maui/issues/15211
+//https://github.com/dotnet/maui/issues/15211#issuecomment-1557569889
+using NUnit.Framework;
+using UITest.Appium;
+using UITest.Core;
+
+namespace Microsoft.Maui.TestCases.Tests.Issues;
+
+public class Issue29092Flyout : _IssuesUITest
+{
+ public Issue29092Flyout(TestDevice testDevice) : base(testDevice)
+ {
+ }
+
+ public override string Issue => "Flyout - Auto Resize chrome icons on iOS to make it more consistent with other platforms - hamburger icon";
+
+ [Test]
+ [Category(UITestCategories.FlyoutPage)]
+ public void FlyoutIconShouldAutoscale()
+ {
+ App.WaitForElement("HelloWorldLabel");
+ VerifyScreenshot();
+ }
+}
+#endif
\ No newline at end of file
diff --git a/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/FlyoutIconShouldAutoscale.png b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/FlyoutIconShouldAutoscale.png
new file mode 100644
index 000000000000..94efd683b2bf
Binary files /dev/null and b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/FlyoutIconShouldAutoscale.png differ
diff --git a/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/ForegroundColorShouldbeSetandCustomIconAlignedProperly.png b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/ForegroundColorShouldbeSetandCustomIconAlignedProperly.png
new file mode 100644
index 000000000000..5b77ee97c9cf
Binary files /dev/null and b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/ForegroundColorShouldbeSetandCustomIconAlignedProperly.png differ
diff --git a/src/Graphics/src/Graphics/Platforms/iOS/UIImageExtensions.cs b/src/Graphics/src/Graphics/Platforms/iOS/UIImageExtensions.cs
index 4c30eae135b6..e367e6a1661b 100644
--- a/src/Graphics/src/Graphics/Platforms/iOS/UIImageExtensions.cs
+++ b/src/Graphics/src/Graphics/Platforms/iOS/UIImageExtensions.cs
@@ -1,3 +1,4 @@
+using System;
using CoreGraphics;
using UIKit;
@@ -25,6 +26,26 @@ public static UIImage ScaleImage(this UIImage target, float maxWidth, float maxH
return ScaleImage(target, new CGSize(targetWidth, targetHeight), disposeOriginal);
}
+ internal static UIImage ResizeImageSource(this UIImage sourceImage, nfloat maxWidth, nfloat maxHeight, CGSize originalImageSize, bool shouldScaleUp = false)
+ {
+ if (sourceImage?.CGImage is null)
+ {
+ return null;
+ }
+
+ maxWidth = (nfloat)Math.Min(maxWidth, originalImageSize.Width);
+ maxHeight = (nfloat)Math.Min(maxHeight, originalImageSize.Height);
+
+ var sourceSize = sourceImage.Size;
+
+ float maxResizeFactor = (float)Math.Min(maxWidth / sourceSize.Width, maxHeight / sourceSize.Height);
+
+ if (maxResizeFactor > 1 && !shouldScaleUp)
+ return sourceImage;
+
+ return UIImage.FromImage(sourceImage.CGImage, sourceImage.CurrentScale / maxResizeFactor, sourceImage.Orientation);
+ }
+
public static UIImage ScaleImage(this UIImage target, CGSize size, bool disposeOriginal = false)
{
UIGraphics.BeginImageContext(size);