From 51040623abd5ea56abfa441c2a8a1d34a3b47017 Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Wed, 30 Oct 2024 15:08:28 -0500 Subject: [PATCH] Fix Button Regression with null image source (#25485) (#25611) Co-authored-by: TJ Lambert <50846373+tj-devel709@users.noreply.github.com> --- src/Controls/src/Core/Button/Button.iOS.cs | 46 ++++++++++------ .../TestCases.HostApp/Issues/Issue25409.xaml | 11 ++++ .../Issues/Issue25409.xaml.cs | 54 +++++++++++++++++++ .../Tests/Issues/Issue25409.cs | 28 ++++++++++ 4 files changed, 122 insertions(+), 17 deletions(-) create mode 100644 src/Controls/tests/TestCases.HostApp/Issues/Issue25409.xaml create mode 100644 src/Controls/tests/TestCases.HostApp/Issues/Issue25409.xaml.cs create mode 100644 src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue25409.cs diff --git a/src/Controls/src/Core/Button/Button.iOS.cs b/src/Controls/src/Core/Button/Button.iOS.cs index a8f322005574..d5776d32421a 100644 --- a/src/Controls/src/Core/Button/Button.iOS.cs +++ b/src/Controls/src/Core/Button/Button.iOS.cs @@ -14,10 +14,10 @@ namespace Microsoft.Maui.Controls { public partial class Button : ICrossPlatformLayout { - // _originalImageSize and _originalImageSource are used to ensure we don't resize the image - // larger than the original image size and to ensure if a new image is loaded, we use that image's size for resizing. + // _originalImage and _originalImageSize are used to ensure we don't resize the image larger than the original image size + // and to ensure if a new image is loaded, we use that image's size for resizing. + CGImage _originalCGImage = null; CGSize _originalImageSize = CGSize.Empty; - string _originalImageSource = string.Empty; /// /// Measure the desired size of the button based on the image and title size taking into account @@ -83,20 +83,19 @@ Size ICrossPlatformLayout.CrossPlatformMeasure(double widthConstraint, double he if (image is not null) { - // Save the original image size for later image resizing - if (_originalImageSize == CGSize.Empty || _originalImageSource == string.Empty || _originalImageSource != button.ImageSource.ToString()) - { - _originalImageSource = button.ImageSource.ToString(); - _originalImageSize = image.Size; - } - // Resize the image if necessary and then update the image variable - if (ResizeImageIfNecessary(platformButton, button, image, padding, spacing, borderWidth, widthConstraint, heightConstraint, _originalImageSize)) + if (ResizeImageIfNecessary(platformButton, button, image, padding, spacing, borderWidth, widthConstraint, heightConstraint)) { image = platformButton.CurrentImage; } } + else + { + _originalCGImage = null; + _originalImageSize = CGSize.Empty; + } + platformButton.ImageView.ContentMode = contentMode; // This is used to match the behavior between platforms. @@ -334,10 +333,16 @@ CGRect ComputeTitleRect (UIButton platformButton, Button button, UIImage image, /// /// /// - /// /// - static bool ResizeImageIfNecessary(UIButton platformButton, Button button, UIImage image, Thickness padding, double spacing, double borderWidth, double widthConstraint, double heightConstraint, CGSize originalImageSize) + bool ResizeImageIfNecessary(UIButton platformButton, Button button, UIImage image, Thickness padding, double spacing, double borderWidth, double widthConstraint, double heightConstraint) { + // Save the original image for later image resizing + if (_originalImageSize == CGSize.Empty || _originalCGImage is null || image.CGImage != _originalCGImage) + { + _originalCGImage = image.CGImage; + _originalImageSize = image.Size; + } + var currentImageWidth = image.Size.Width; var currentImageHeight = image.Size.Height; @@ -387,15 +392,15 @@ static bool ResizeImageIfNecessary(UIButton platformButton, Button button, UIIma // 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 = ResizeImageSource(image, 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 && availableWidth - additionalHorizontalSpace - currentImageWidth > buffer - && currentImageHeight != originalImageSize.Height - && currentImageWidth != originalImageSize.Width) + && currentImageHeight != _originalImageSize.Height + && currentImageWidth != _originalImageSize.Width) { - image = ResizeImageSource(image, (nfloat)widthConstraint - additionalHorizontalSpace, (nfloat)heightConstraint - additionalVerticalSpace, originalImageSize, true); + image = ResizeImageSource(image, (nfloat)widthConstraint - additionalHorizontalSpace, (nfloat)heightConstraint - additionalVerticalSpace, _originalImageSize, true); } else { @@ -465,5 +470,12 @@ internal static void MapBorderWidth(IButtonHandler handler, Button button) { handler.PlatformView?.UpdateContentLayout(button); } + + private protected override void OnHandlerChangingCore(HandlerChangingEventArgs args) + { + base.OnHandlerChangingCore(args); + _originalImageSize = CGSize.Empty; + _originalCGImage = null; + } } } diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue25409.xaml b/src/Controls/tests/TestCases.HostApp/Issues/Issue25409.xaml new file mode 100644 index 000000000000..ef8b9050e197 --- /dev/null +++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue25409.xaml @@ -0,0 +1,11 @@ + + +