Skip to content

Commit

Permalink
Only use custom image sizing with ImageButtons (#18521)
Browse files Browse the repository at this point in the history
* Only use custom sizing with ImageButtons

ImageButtons have a null value for CurrentTitle and can't have Text on them, giving us a way to distinguish Imagebuttons from normal buttons.

Normal buttons with images should still use the standard sizing logic

* Add test
  • Loading branch information
jknaudt21 authored Nov 14, 2023
1 parent 6ec214f commit 78e64c2
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 3 deletions.
42 changes: 42 additions & 0 deletions src/Controls/tests/DeviceTests/Elements/Button/ButtonTests.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System;
using System.Threading.Tasks;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Handlers;
using UIKit;
using Xunit;
Expand Down Expand Up @@ -36,5 +37,46 @@ public async Task ClickedWorksAfterGC()
await InvokeOnMainThreadAsync(() => handler.PlatformView.SendActionForControlEvents(UIControlEvent.TouchUpInside));
Assert.True(fired, "Button.Clicked did not fire!");
}

[Theory("Button with image lays out correctly")]
[InlineData(true)]
[InlineData(false)]
public async Task ButtonWithImage(bool includeText)
{
var gridHeight = 300;
var gridWidth = 300;

var button = new Button {BackgroundColor = Colors.Yellow, VerticalOptions = LayoutOptions.Center, HorizontalOptions = LayoutOptions.Center};
if (includeText)
{
button.Text = "Hello world!";
}

var layout = new Grid() {HeightRequest = gridHeight, WidthRequest = gridWidth, BackgroundColor = Colors.Blue };
layout.Add(button);

var buttonHandler = await CreateHandlerAsync<ButtonHandler>(button);
var handler = await CreateHandlerAsync<LayoutHandler>(layout);

await InvokeOnMainThreadAsync(async () =>
{
button.ImageSource = ImageSource.FromFile("red.png");

// Wait for image to load and force the grid to measure itself again
await Task.Delay(1000);
layout.Measure(double.PositiveInfinity, double.PositiveInfinity);

await handler.ToPlatform().AssertContainsColor(Colors.Blue, MauiContext); // Grid renders
await handler.ToPlatform().AssertContainsColor(Colors.Red, MauiContext); // Image within button renders
await handler.ToPlatform().AssertContainsColor(Colors.Yellow, MauiContext); // Button renders
});

// red.png is 100x100
Assert.True(button.Width > 100, $"Button should have larger width than its image. Exepected: 100>, was {button.Width}");
Assert.True(button.Height > 100, $"Button should have larger height than its image. Exepected: 100>, was {button.Height}");

Assert.True(button.Width < gridWidth, $"Button shouldn't occupy entire layout width. Expected: {gridWidth}<, was {button.Width}");
Assert.True(button.Height < gridHeight, $"Button shouldn't occupy entire layout height. Expected: {gridHeight}<, was {button.Height}");
}
}
}
2 changes: 1 addition & 1 deletion src/Core/src/Handlers/ViewHandlerExtensions.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ internal static Size GetDesiredSizeFromHandler(this IViewHandler viewHandler, do

sizeThatFits = imageView.SizeThatFitsImage(new CGSize((float)widthConstraint, (float)heightConstraint));
}
else if (platformView is UIButton imageButton && imageButton.ImageView?.Image is not null)
else if (platformView is UIButton imageButton && imageButton.ImageView?.Image is not null && imageButton.CurrentTitle is null)
{
widthConstraint = IsExplicitSet(virtualView.Width) ? virtualView.Width : widthConstraint;
heightConstraint = IsExplicitSet(virtualView.Height) ? virtualView.Height : heightConstraint;
Expand Down
4 changes: 2 additions & 2 deletions src/Core/src/Platform/iOS/WrapperView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ public override CGSize SizeThatFits(CGSize size)
{
return imageView.SizeThatFitsImage(size);
}
else if (child is UIButton imageButton && imageButton.ImageView?.Image is not null)
else if (child is UIButton imageButton && imageButton.ImageView?.Image is not null && imageButton.CurrentTitle is null)
{
return imageButton.ImageView.SizeThatFitsImage(size);
}
Expand All @@ -141,7 +141,7 @@ internal CGSize SizeThatFitsWrapper(CGSize originalSpec, double virtualViewWidth

var child = Subviews[0];

if (child is UIImageView || (child is UIButton imageButton && imageButton.ImageView?.Image is not null))
if (child is UIImageView || (child is UIButton imageButton && imageButton.ImageView?.Image is not null && imageButton.CurrentTitle is null))
{
var widthConstraint = IsExplicitSet(virtualViewWidth) ? virtualViewWidth : originalSpec.Width;
var heightConstraint = IsExplicitSet(virtualViewHeight) ? virtualViewHeight : originalSpec.Height;
Expand Down

0 comments on commit 78e64c2

Please sign in to comment.