Skip to content

Add support for Font to Button and Entry #500

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

Merged
merged 9 commits into from
Mar 14, 2021
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ void UpdateEnabled()
Control.Enabled = Element.IsEnabled;
}

[PortHandler]
void UpdateFont()
{
Button button = Element;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ void Initialize()
Tag = this;
}

[PortHandler]
void UpdateFont()
{
if (Element == null || _isDisposed)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ void UpdateColor()
SetTextColor(c.ToAndroid());
}

[PortHandler]
void UpdateFont()
{
Font f = Font.OfSize(Element.FontFamily, Element.FontSize).WithAttributes(Element.FontAttributes);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ void UpdateVerticalTextAlignment()
protected abstract void UpdateColor();
protected abstract void UpdateTextColor(Color color);

[PortHandler]
protected virtual void UpdateFont()
{
EditText.Typeface = Element.ToTypeface();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ void OnButtonTouchDown(object sender, EventArgs eventArgs)
ButtonElementManager.OnButtonTouchDown(this.Element);
}

[PortHandler]
void UpdateFont()
{
Control.TitleLabel.Font = Element.ToUIFont();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ void UpdateAdjustsFontSizeToFitWidth()
Control.AdjustsFontSizeToFitWidth = Element.OnThisPlatform().AdjustsFontSizeToFitWidth();
}

[PortHandler]
protected virtual void UpdateFont()
{
if (initialSize == CGSize.Empty)
Expand Down
11 changes: 11 additions & 0 deletions src/Core/src/Handlers/Button/ButtonHandler.Android.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using Android.Views;
using AndroidX.AppCompat.Widget;
using Microsoft.Extensions.DependencyInjection;
using AView = Android.Views.View;

namespace Microsoft.Maui.Handlers
Expand Down Expand Up @@ -51,6 +53,15 @@ public static void MapTextColor(ButtonHandler handler, IButton button)
handler.TypedNativeView?.UpdateTextColor(button);
}

public static void MapFont(ButtonHandler handler, IButton button)
{
var services = App.Current?.Services
?? throw new InvalidOperationException($"Unable to find service provider, the App.Current.Services was null.");
var fontManager = services.GetRequiredService<IFontManager>();

handler.TypedNativeView?.UpdateFont(button, fontManager);
}

public static void MapPadding(ButtonHandler handler, IButton button)
{
handler.TypedNativeView?.UpdatePadding(button);
Expand Down
1 change: 1 addition & 0 deletions src/Core/src/Handlers/Button/ButtonHandler.Standard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public partial class ButtonHandler : AbstractViewHandler<IButton, object>

public static void MapText(ButtonHandler handler, IButton button) { }
public static void MapTextColor(ButtonHandler handler, IButton button) { }
public static void MapFont(ButtonHandler handler, IButton button) { }
public static void MapPadding(ButtonHandler handler, IButton button) { }
}
}
1 change: 1 addition & 0 deletions src/Core/src/Handlers/Button/ButtonHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ public partial class ButtonHandler
{
[nameof(IButton.Text)] = MapText,
[nameof(IButton.TextColor)] = MapTextColor,
[nameof(ILabel.Font)] = MapFont,
[nameof(IButton.Padding)] = MapPadding,
};

Expand Down
10 changes: 10 additions & 0 deletions src/Core/src/Handlers/Button/ButtonHandler.iOS.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using Microsoft.Extensions.DependencyInjection;
using UIKit;

namespace Microsoft.Maui.Handlers
Expand Down Expand Up @@ -58,6 +59,15 @@ public static void MapPadding(ButtonHandler handler, IButton button)
handler.TypedNativeView?.UpdatePadding(button);
}

public static void MapFont(ButtonHandler handler, IButton button)
{
var services = App.Current?.Services ??
throw new InvalidOperationException($"Unable to find service provider, the App.Current.Services was null.");
var fontManager = services.GetRequiredService<IFontManager>();

handler.TypedNativeView?.UpdateFont(button, fontManager);
}

void SetControlPropertiesFromProxy()
{
if (TypedNativeView == null)
Expand Down
13 changes: 12 additions & 1 deletion src/Core/src/Handlers/Entry/EntryHandler.Android.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using Android.Content.Res;
using System;
using Android.Content.Res;
using Android.Text;
using AndroidX.AppCompat.Widget;
using Microsoft.Extensions.DependencyInjection;

namespace Microsoft.Maui.Handlers
{
Expand Down Expand Up @@ -58,6 +60,15 @@ public static void MapPlaceholder(EntryHandler handler, IEntry entry)
handler.TypedNativeView?.UpdatePlaceholder(entry);
}

public static void MapFont(EntryHandler handler, IEntry entry)
{
var services = App.Current?.Services
?? throw new InvalidOperationException($"Unable to find service provider, the App.Current.Services was null.");
var fontManager = services.GetRequiredService<IFontManager>();

handler.TypedNativeView?.UpdateFont(entry, fontManager);
}

public static void MapIsReadOnly(EntryHandler handler, IEntry entry)
{
handler.TypedNativeView?.UpdateIsReadOnly(entry);
Expand Down
1 change: 1 addition & 0 deletions src/Core/src/Handlers/Entry/EntryHandler.Standard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ public static void MapIsPassword(IViewHandler handler, IEntry entry) { }
public static void MapIsTextPredictionEnabled(IViewHandler handler, IEntry entry) { }
public static void MapPlaceholder(IViewHandler handler, IEntry entry) { }
public static void MapIsReadOnly(IViewHandler handler, IEntry entry) { }
public static void MapFont(IViewHandler handler, IEntry entry) { }
}
}
3 changes: 2 additions & 1 deletion src/Core/src/Handlers/Entry/EntryHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ public partial class EntryHandler
[nameof(IEntry.IsPassword)] = MapIsPassword,
[nameof(IEntry.IsTextPredictionEnabled)] = MapIsTextPredictionEnabled,
[nameof(IEntry.Placeholder)] = MapPlaceholder,
[nameof(IEntry.IsReadOnly)] = MapIsReadOnly
[nameof(IEntry.IsReadOnly)] = MapIsReadOnly,
[nameof(IEntry.Font)] = MapFont
};

public EntryHandler() : base(EntryMapper)
Expand Down
12 changes: 11 additions & 1 deletion src/Core/src/Handlers/Entry/EntryHandler.iOS.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Maui.Platform.iOS;
using UIKit;

Expand Down Expand Up @@ -84,10 +85,19 @@ void OnTextChanged()

// Even though <null> is technically different to "", it has no
// functional difference to apps. Thus, hide it.
var mauiText = VirtualView.Text ?? string.Empty;
var mauiText = VirtualView!.Text ?? string.Empty;
var nativeText = TypedNativeView.Text ?? string.Empty;
if (mauiText != nativeText)
VirtualView.Text = nativeText;
}

public static void MapFont(EntryHandler handler, IEntry entry)
{
var services = App.Current?.Services
?? throw new InvalidOperationException($"Unable to find service provider, the App.Current.Services was null.");
var fontManager = services.GetRequiredService<IFontManager>();

handler.TypedNativeView?.UpdateFont(entry, fontManager);
}
}
}
12 changes: 12 additions & 0 deletions src/Core/src/Platform/Android/ButtonExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Android.Util;
using Android.Content.Res;
using AndroidX.AppCompat.Widget;
using XColor = Microsoft.Maui.Color;
Expand All @@ -23,6 +24,17 @@ public static void UpdateTextColor(this AppCompatButton button, XColor color, Co
public static void UpdateTextColor(this AppCompatButton appCompatButton, IButton button, XColor defaultColor) =>
appCompatButton.SetTextColor(button.TextColor.Cleanse(defaultColor).ToNative());

public static void UpdateFont(this AppCompatButton appCompatButton, IButton button, IFontManager fontManager)
{
var font = button.Font;

var tf = fontManager.GetTypeface(font);
appCompatButton.Typeface = tf;

var sp = fontManager.GetScaledPixel(font);
appCompatButton.SetTextSize(ComplexUnitType.Sp, sp);
}

public static void UpdatePadding(this AppCompatButton appCompatButton, IButton button)
{
var context = appCompatButton.Context;
Expand Down
14 changes: 13 additions & 1 deletion src/Core/src/Platform/Android/EntryExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Android.Content.Res;
using Android.Util;
using Android.Content.Res;
using Android.Text;
using AndroidX.AppCompat.Widget;

Expand Down Expand Up @@ -84,5 +85,16 @@ public static void UpdateIsReadOnly(this AppCompatEditText editText, IEntry entr
editText.FocusableInTouchMode = isEditable;
editText.Focusable = isEditable;
}

public static void UpdateFont(this AppCompatEditText editText, IEntry entry, IFontManager fontManager)
{
var font = entry.Font;

var tf = fontManager.GetTypeface(font);
editText.Typeface = tf;

var sp = fontManager.GetScaledPixel(font);
editText.SetTextSize(ComplexUnitType.Sp, sp);
}
}
}
7 changes: 6 additions & 1 deletion src/Core/src/Platform/iOS/ButtonExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ public static void UpdateTextColor(this UIButton nativeButton, IButton button, U
}
}

public static void UpdateFont(this UIButton nativeButton, IButton button, IFontManager fontManager)
{
var uiFont = fontManager.GetFont(button.Font);
nativeButton.TitleLabel.Font = uiFont;
}

public static void UpdatePadding(this UIButton nativeButton, IButton button)
{
nativeButton.ContentEdgeInsets = new UIEdgeInsets(
Expand All @@ -39,6 +45,5 @@ public static void UpdatePadding(this UIButton nativeButton, IButton button)
(float)button.Padding.Bottom,
(float)button.Padding.Right);
}

}
}
6 changes: 6 additions & 0 deletions src/Core/src/Platform/iOS/EntryExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,11 @@ public static void UpdateIsReadOnly(this UITextField textField, IEntry entry)
{
textField.UserInteractionEnabled = !entry.IsReadOnly;
}

public static void UpdateFont(this UITextField textField, IEntry entry, IFontManager fontManager)
{
var uiFont = fontManager.GetFont(entry.Font);
textField.Font = uiFont;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Threading.Tasks;
using AndroidX.AppCompat.Widget;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Maui.DeviceTests.Stubs;
using Microsoft.Maui.Handlers;
using Xunit;
Expand All @@ -9,6 +10,33 @@ namespace Microsoft.Maui.DeviceTests
{
public partial class ButtonHandlerTests
{
[Theory(DisplayName = "Font Family Initializes Correctly")]
[InlineData(null)]
[InlineData("monospace")]
[InlineData("Dokdo")]
public async Task FontFamilyInitializesCorrectly(string family)
{
var button = new ButtonStub
{
Text = "Test",
Font = Font.OfSize(family, 10)
};

var handler = await CreateHandlerAsync(button);
var nativeButton = GetNativeButton(handler);

var fontManager = App.Services.GetRequiredService<IFontManager>();

var nativeFont = fontManager.GetTypeface(Font.OfSize(family, 0.0));

Assert.Equal(nativeFont, nativeButton.Typeface);

if (string.IsNullOrEmpty(family))
Assert.Equal(fontManager.DefaultTypeface, nativeButton.Typeface);
else
Assert.NotEqual(fontManager.DefaultTypeface, nativeButton.Typeface);
}

[Fact(DisplayName = "Button Padding Initializing")]
public async Task PaddingInitializesCorrectly()
{
Expand Down Expand Up @@ -71,5 +99,17 @@ Task PerformClick(IButton button)
GetNativeButton(CreateHandler(button)).PerformClick();
});
}

double GetNativeUnscaledFontSize(ButtonHandler buttonHandler)
{
var textView = GetNativeButton(buttonHandler);
return textView.TextSize / textView.Resources.DisplayMetrics.Density;
}

bool GetNativeIsBold(ButtonHandler buttonHandler) =>
GetNativeButton(buttonHandler).Typeface.IsBold;

bool GetNativeIsItalic(ButtonHandler buttonHandler) =>
GetNativeButton(buttonHandler).Typeface.IsItalic;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,38 @@ public async Task ClickEventFires()

Assert.True(clicked);
}

[Theory(DisplayName = "Font Size Initializes Correctly")]
[InlineData(1)]
[InlineData(10)]
[InlineData(20)]
[InlineData(100)]
public async Task FontSizeInitializesCorrectly(int fontSize)
{
var button = new ButtonStub()
{
Text = "Test",
Font = Font.OfSize("Arial", fontSize)
};

await ValidatePropertyInitValue(button, () => button.Font.FontSize, GetNativeUnscaledFontSize, button.Font.FontSize);
}

[Theory(DisplayName = "Font Attributes Initialize Correctly")]
[InlineData(FontAttributes.None, false, false)]
[InlineData(FontAttributes.Bold, true, false)]
[InlineData(FontAttributes.Italic, false, true)]
[InlineData(FontAttributes.Bold | FontAttributes.Italic, true, true)]
public async Task FontAttributesInitializeCorrectly(FontAttributes attributes, bool isBold, bool isItalic)
{
var button = new ButtonStub()
{
Text = "Test",
Font = Font.OfSize("Arial", 10).WithAttributes(attributes)
};

await ValidatePropertyInitValue(button, () => button.Font.FontAttributes.HasFlag(FontAttributes.Bold), GetNativeIsBold, isBold);
await ValidatePropertyInitValue(button, () => button.Font.FontAttributes.HasFlag(FontAttributes.Italic), GetNativeIsItalic, isItalic);
}
}
}
Loading