Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't worry about the size of the text #21628

Merged
merged 5 commits into from
Apr 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
#nullable enable
using System.Threading.Tasks;
using Android.Text;
using AndroidX.AppCompat.Widget;
using AndroidX.Core.Widget;
using Google.Android.Material.Button;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Maui.DeviceTests.Stubs;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Hosting;
using System.Threading.Tasks;
using Xunit;
using AColor = global::Android.Graphics.Color;
using System;

namespace Microsoft.Maui.DeviceTests
{
Expand All @@ -23,7 +21,63 @@ public partial class ButtonTests
return InvokeOnMainThreadAsync(() => GetPlatformButton(buttonHandler).Text);
}

TextUtils.TruncateAt? GetPlatformLineBreakMode(ButtonHandler buttonHandler) =>
Android.Text.TextUtils.TruncateAt? GetPlatformLineBreakMode(ButtonHandler buttonHandler) =>
GetPlatformButton(buttonHandler).Ellipsize;


[Theory(DisplayName = "Button Icon has Correct Position"), Category(TestCategory.Layout)]
[InlineData(Button.ButtonContentLayout.ImagePosition.Left)]
[InlineData(Button.ButtonContentLayout.ImagePosition.Top)]
[InlineData(Button.ButtonContentLayout.ImagePosition.Right)]
[InlineData(Button.ButtonContentLayout.ImagePosition.Bottom)]
public async Task NestedButtonHasExpectedIconPosition(Button.ButtonContentLayout.ImagePosition imagePosition)
{
EnsureHandlerCreated(builder =>
{
builder.ConfigureMauiHandlers(handlers =>
{
handlers.AddHandler<Page, PageHandler>();
handlers.AddHandler<Window, WindowHandlerStub>();
handlers.AddHandler<Layout, LayoutHandler>();
handlers.AddHandler<Button, ButtonHandler>();
});
});

var button = new Button()
{
Text = "Hello",
ImageSource = "red.png",
ContentLayout = new Button.ButtonContentLayout(imagePosition, 8)
};

var page = new ContentPage()
{
Content = new HorizontalStackLayout()
{
button
}
};

await CreateHandlerAndAddToWindow(page, () =>
{
var handler = CreateHandler<ButtonHandler>(button);

var platformButton = (AppCompatButton)handler.PlatformView;

int matchingDrawableIndex = imagePosition switch
{
Button.ButtonContentLayout.ImagePosition.Left => 0,
Button.ButtonContentLayout.ImagePosition.Top => 1,
Button.ButtonContentLayout.ImagePosition.Right => 2,
Button.ButtonContentLayout.ImagePosition.Bottom => 3,
_ => throw new InvalidOperationException(),
};

// Assert that the image is in the expected position
var drawables = TextViewCompat.GetCompoundDrawablesRelative(platformButton);
Assert.NotNull(drawables[matchingDrawableIndex]);
});
}

}
}
Original file line number Diff line number Diff line change
@@ -1,73 +1,10 @@
using System;
using System.Threading.Tasks;
using Android.Graphics.Drawables;
using AndroidX.AppCompat.Widget;
using AndroidX.Core.Widget;
using Microsoft.Maui.Controls;
using Microsoft.Maui.DeviceTests.Stubs;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Hosting;
using Microsoft.Maui.Platform;
using Xunit;

namespace Microsoft.Maui.DeviceTests
{
public partial class LayoutTests
{
[Theory(DisplayName = "Button Icon has Correct Position"), Category(TestCategory.Layout)]
[InlineData(Button.ButtonContentLayout.ImagePosition.Left)]
[InlineData(Button.ButtonContentLayout.ImagePosition.Top)]
[InlineData(Button.ButtonContentLayout.ImagePosition.Right)]
[InlineData(Button.ButtonContentLayout.ImagePosition.Bottom)]
public async Task NestedButtonHasExpectedIconPosition(Button.ButtonContentLayout.ImagePosition imagePosition)
{
EnsureHandlerCreated(builder =>
{
builder.ConfigureMauiHandlers(handlers =>
{
handlers.AddHandler<Page, PageHandler>();
handlers.AddHandler<Window, WindowHandlerStub>();
handlers.AddHandler<Layout, LayoutHandler>();
handlers.AddHandler<Button, ButtonHandler>();
});
});

var button = new Button()
{
Text = "Hello",
ImageSource = "red.png",
ContentLayout = new Button.ButtonContentLayout(imagePosition, 8)
};

var page = new ContentPage()
{
Content = new HorizontalStackLayout()
{
button
}
};

await CreateHandlerAndAddToWindow(page, () =>
{
var handler = CreateHandler<ButtonHandler>(button);

var platformButton = (AppCompatButton)handler.PlatformView;

int matchingDrawableIndex = imagePosition switch
{
Button.ButtonContentLayout.ImagePosition.Left => 0,
Button.ButtonContentLayout.ImagePosition.Top => 1,
Button.ButtonContentLayout.ImagePosition.Right => 2,
Button.ButtonContentLayout.ImagePosition.Bottom => 3,
_ => throw new InvalidOperationException(),
};

// Assert that the image is in the expected position
Drawable[] drawables = TextViewCompat.GetCompoundDrawablesRelative(platformButton);
Assert.NotNull(drawables[matchingDrawableIndex]);
});
}

void ValidateInputTransparentOnPlatformView(IView view)
{
var handler = view.ToHandler(MauiContext);
Expand Down
3 changes: 2 additions & 1 deletion src/Core/src/Handlers/Button/ButtonHandler.Android.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Threading.Tasks;
using Android.Content.Res;
using Android.Graphics.Drawables;
Expand Down Expand Up @@ -189,7 +190,7 @@ public override void SetImageSource(Drawable? platformImage)

button.Icon = platformImage is null
? null
: new MauiMaterialButton.MauiResizableDrawable(platformImage);
: (OperatingSystem.IsAndroidVersionAtLeast(23)) ? new MauiMaterialButton.MauiResizableDrawable(platformImage) : platformImage;
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/Core/src/Handlers/ElementHandlerExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,5 +95,9 @@ public static bool CanInvokeMappers(this IElementHandler viewHandler)
#endif
return true;
}

internal static bool IsConnected(this IElementHandler handler) =>
handler.PlatformView is not null;

}
}
12 changes: 8 additions & 4 deletions src/Core/src/Handlers/Image/ImageHandler.Android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,16 @@ public static void MapBackground(IImageHandler handler, IImage image)
public static void MapSource(IImageHandler handler, IImage image) =>
MapSourceAsync(handler, image).FireAndForget(handler);

public static Task MapSourceAsync(IImageHandler handler, IImage image)
public static async Task MapSourceAsync(IImageHandler handler, IImage image)
{
return handler
await handler
.SourceLoader
.UpdateImageSourceAsync()
.ContinueWith((action) => handler.UpdateValue(nameof(IImage.IsAnimationPlaying)));
.UpdateImageSourceAsync();

// Because this resolves from a task we should validate that the
// handler hasn't been disconnected
if (handler.IsConnected())
handler.UpdateValue(nameof(IImage.IsAnimationPlaying));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was occasionally causing a crash in our device tests.

Also, I don't think we ever should have used ContinueWith here, I don't think ContinueWith will resolve on the synchronization context. I'm pretty sure the code inside ContinueWith will be on a task pool thread unless you pass TaskScheduler.FromCurrentSynchronizationContext()

}

public override void PlatformArrange(Graphics.Rect frame)
Expand Down
5 changes: 4 additions & 1 deletion src/Core/src/Handlers/Image/ImageHandler.Windows.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ public static void MapBackground(IImageHandler handler, IImage image)

void OnImageOpened(object sender, RoutedEventArgs e)
{
UpdateValue(nameof(IImage.IsAnimationPlaying));
// Because this resolves from a task we should validate that the
// handler hasn't been disconnected
if (this.IsConnected())
UpdateValue(nameof(IImage.IsAnimationPlaying));
}

partial class ImageImageSourcePartSetter
Expand Down