|
4 | 4 | using CoreGraphics; |
5 | 5 | using Foundation; |
6 | 6 | using Microsoft.Maui.Graphics; |
| 7 | +using Microsoft.Maui.Graphics.Platform; |
7 | 8 | using Microsoft.Maui.Platform; |
8 | 9 | using ObjCRuntime; |
9 | 10 | using UIKit; |
@@ -57,6 +58,37 @@ internal static SecondarySubToolbarItem ToSecondarySubToolbarItem(this ToolbarIt |
57 | 58 | return new SecondarySubToolbarItem(item, action); |
58 | 59 | } |
59 | 60 |
|
| 61 | + static UIImage ScaleImageToSystemDefaults(ImageSource imageSource, UIImage uIImage) |
| 62 | + { |
| 63 | + var icon = imageSource is not FontImageSource |
| 64 | + ? uIImage?.ImageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal) |
| 65 | + : uIImage; |
| 66 | + |
| 67 | + var originalImageSize = icon?.Size ?? CGSize.Empty; |
| 68 | + |
| 69 | + // The largest height you can use for navigation bar icons in iOS. |
| 70 | + // Per Apple's Human Interface Guidelines, the navigation bar height is 44 points, |
| 71 | + // so using the full height ensures maximum visual clarity and maintains consistency |
| 72 | + // with iOS design standards. This allows icons to utilize the entire available |
| 73 | + // vertical space within the navigation bar container. |
| 74 | + var defaultIconHeight = 44f; |
| 75 | + var buffer = 0.1; |
| 76 | + // We only check height because the navigation bar constrains vertical space (44pt height), |
| 77 | + // but allows horizontal flexibility. Width can vary based on icon design and content, |
| 78 | + // while height must fit within the fixed navigation bar bounds to avoid clipping. |
| 79 | + |
| 80 | + // if the image is bigger than the default available size, resize it |
| 81 | + if (icon is not null && originalImageSize.Height - defaultIconHeight > buffer) |
| 82 | + { |
| 83 | + if (imageSource is not FontImageSource fontImageSource || !fontImageSource.IsSet(FontImageSource.SizeProperty)) |
| 84 | + { |
| 85 | + icon = icon.ResizeImageSource(originalImageSize.Width, defaultIconHeight, originalImageSize); |
| 86 | + } |
| 87 | + } |
| 88 | + |
| 89 | + return icon; |
| 90 | + } |
| 91 | + |
60 | 92 | sealed class PrimaryToolbarItem : UIBarButtonItem |
61 | 93 | { |
62 | 94 | readonly bool _forceName; |
@@ -146,9 +178,7 @@ void UpdateIconAndStyle(ToolbarItem item) |
146 | 178 | } |
147 | 179 | item.IconImageSource.LoadImage(mauiContext, result => |
148 | 180 | { |
149 | | - Image = item.IconImageSource is not FontImageSource |
150 | | - ? result?.Value.ImageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal) |
151 | | - : result?.Value; |
| 181 | + Image = ScaleImageToSystemDefaults(item.IconImageSource, result?.Value); |
152 | 182 | Style = UIBarButtonItemStyle.Plain; |
153 | 183 | }); |
154 | 184 | } |
@@ -304,11 +334,11 @@ void OnPropertyChanged(object sender, PropertyChangedEventArgs e) |
304 | 334 |
|
305 | 335 | void UpdateIcon(ToolbarItem item) |
306 | 336 | { |
307 | | - if (item.IconImageSource != null && !item.IconImageSource.IsEmpty) |
| 337 | + if (item.IconImageSource is not null && !item.IconImageSource.IsEmpty) |
308 | 338 | { |
309 | 339 | item.IconImageSource.LoadImage(item.FindMauiContext(), result => |
310 | 340 | { |
311 | | - ((SecondaryToolbarItemContent)CustomView).Image = result?.Value; |
| 341 | + ((SecondaryToolbarItemContent)CustomView).Image = ScaleImageToSystemDefaults(item.IconImageSource, result?.Value); |
312 | 342 | }); |
313 | 343 | } |
314 | 344 | else |
|
0 commit comments