Skip to content

Commit

Permalink
Implement Font properties in SearchBarHandlers (#533)
Browse files Browse the repository at this point in the history
* Speed up PR builds (#510)

Reduce the jobs and use the new pools

* implement Font properties in SearchBarHandlers

* Fix rebase issues

Co-authored-by: Matthew Leibowitz <[email protected]>
Co-authored-by: E.Z. Hart <[email protected]>
  • Loading branch information
3 people committed Mar 18, 2021
1 parent 2798eb9 commit 6ec9b0e
Show file tree
Hide file tree
Showing 15 changed files with 228 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ void ClearFocus(SearchView view)
view.ClearFocus();
}

[PortHandler]
void UpdateFont()
{
_editText = _editText ?? Control.GetChildrenOfType<EditText>().FirstOrDefault();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ public virtual void UpdateCancelButton()
}
}

[PortHandler]
void UpdateFont()
{
_textField = _textField ?? Control.FindDescendantView<UITextField>();
Expand Down
12 changes: 2 additions & 10 deletions src/Core/src/Core/ISearchBar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,8 @@
/// <summary>
/// Represents a View used to initiating a search.
/// </summary>
public interface ISearchBar : IView, IPlaceholder, ITextAlignment
public interface ISearchBar : IView, IText, IPlaceholder, ITextAlignment
{
/// <summary>
/// Gets a string containing the query text in the SearchBar.
/// </summary>
string Text { get; }

/// <summary>
/// Gets a string containing the query text in the SearchBar.
/// </summary>
double CharacterSpacing { get; }

}
}
13 changes: 12 additions & 1 deletion src/Core/src/Handlers/SearchBar/SearchBarHandler.Android.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System.Linq;
using System;
using System.Linq;
using Android.Widget;
using Microsoft.Extensions.DependencyInjection;
using SearchView = AndroidX.AppCompat.Widget.SearchView;

namespace Microsoft.Maui.Handlers
Expand Down Expand Up @@ -28,6 +30,15 @@ public static void MapPlaceholder(SearchBarHandler handler, ISearchBar searchBar
handler.TypedNativeView?.UpdatePlaceholder(searchBar);
}

public static void MapFont(SearchBarHandler handler, ISearchBar searchBar)
{
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(searchBar, fontManager, handler._editText);
}

public static void MapHorizontalTextAlignment(SearchBarHandler handler, ISearchBar searchBar)
{
handler.QueryEditor?.UpdateHorizontalTextAlignment(searchBar);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public partial class SearchBarHandler : AbstractViewHandler<ISearchBar, object>

public static void MapText(IViewHandler handler, ISearchBar searchBar) { }
public static void MapPlaceholder(IViewHandler handler, ISearchBar searchBar) { }
public static void MapFont(IViewHandler handler, ISearchBar searchBar) { }
public static void MapHorizontalTextAlignment(IViewHandler handler, ISearchBar searchBar) { }
public static void MapCharacterSpacing(IViewHandler handler, ISearchBar searchBar) { }
}
Expand Down
1 change: 1 addition & 0 deletions src/Core/src/Handlers/SearchBar/SearchBarHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ public partial class SearchBarHandler
{
[nameof(ISearchBar.Text)] = MapText,
[nameof(ISearchBar.Placeholder)] = MapPlaceholder,
[nameof(ISearchBar.Font)] = MapFont,
[nameof(ISearchBar.HorizontalTextAlignment)] = MapHorizontalTextAlignment,
[nameof(ISearchBar.CharacterSpacing)] = MapCharacterSpacing
};
Expand Down
13 changes: 13 additions & 0 deletions src/Core/src/Handlers/SearchBar/SearchBarHandler.iOS.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System;
using System.Drawing;
using Microsoft.Extensions.DependencyInjection;
using UIKit;

namespace Microsoft.Maui.Handlers
Expand Down Expand Up @@ -27,6 +29,17 @@ public static void MapPlaceholder(SearchBarHandler handler, ISearchBar searchBar
handler.TypedNativeView?.UpdatePlaceholder(searchBar);
}

// TODO ezhart The extension methods are handling the dependent property updates; those should be in the mapping

public static void MapFont(SearchBarHandler handler, ISearchBar searchBar)
{
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.QueryEditor?.UpdateFont(searchBar, fontManager);
}

public static void MapHorizontalTextAlignment(SearchBarHandler handler, ISearchBar searchBar)
{
handler.QueryEditor?.UpdateHorizontalTextAlignment(searchBar);
Expand Down
26 changes: 25 additions & 1 deletion src/Core/src/Platform/Android/SearchBarExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using SearchView = AndroidX.AppCompat.Widget.SearchView;
using System.Linq;
using Android.Util;
using Android.Widget;
using SearchView = AndroidX.AppCompat.Widget.SearchView;

namespace Microsoft.Maui
{
Expand All @@ -13,5 +16,26 @@ public static void UpdatePlaceholder(this SearchView searchView, ISearchBar sear
{
searchView.QueryHint = searchBar.Placeholder;
}

public static void UpdateFont(this SearchView searchView, ISearchBar searchBar, IFontManager fontManager)
{
searchView.UpdateFont(searchBar, fontManager, null);
}

public static void UpdateFont(this SearchView searchView, ISearchBar searchBar, IFontManager fontManager, EditText? editText)
{
editText ??= searchView.GetChildrenOfType<EditText>().FirstOrDefault();

if (editText == null)
return;

var font = searchBar.Font;

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

var sp = fontManager.GetScaledPixel(font);
editText.SetTextSize(ComplexUnitType.Sp, sp);
}
}
}
52 changes: 26 additions & 26 deletions src/Core/src/Platform/iOS/LabelExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,32 @@ public static void UpdatePadding(this MauiLabel nativeLabel, ILabel label)
(float)label.Padding.Right);
}

public static void UpdateTextDecorations(this UILabel nativeLabel, ILabel label)
{
if (nativeLabel.AttributedText != null && !(nativeLabel.AttributedText?.Length > 0))
return;

var textDecorations = label?.TextDecorations;

var newAttributedText = nativeLabel.AttributedText != null ? new NSMutableAttributedString(nativeLabel.AttributedText) : new NSMutableAttributedString(label?.Text ?? string.Empty);
var strikeThroughStyleKey = UIStringAttributeKey.StrikethroughStyle;
var underlineStyleKey = UIStringAttributeKey.UnderlineStyle;

var range = new NSRange(0, newAttributedText.Length);

if ((textDecorations & TextDecorations.Strikethrough) == 0)
newAttributedText.RemoveAttribute(strikeThroughStyleKey, range);
else
newAttributedText.AddAttribute(strikeThroughStyleKey, NSNumber.FromInt32((int)NSUnderlineStyle.Single), range);

if ((textDecorations & TextDecorations.Underline) == 0)
newAttributedText.RemoveAttribute(underlineStyleKey, range);
else
newAttributedText.AddAttribute(underlineStyleKey, NSNumber.FromInt32((int)NSUnderlineStyle.Single), range);

nativeLabel.AttributedText = newAttributedText;
}

internal static void SetLineBreakMode(this UILabel nativeLabel, ILabel label)
{
int maxLines = label.MaxLines;
Expand Down Expand Up @@ -113,31 +139,5 @@ internal static void SetLineBreakMode(this UILabel nativeLabel, ILabel label)

nativeLabel.Lines = maxLines;
}

public static void UpdateTextDecorations(this UILabel nativeLabel, ILabel label)
{
if (nativeLabel.AttributedText != null && !(nativeLabel.AttributedText?.Length > 0))
return;

var textDecorations = label?.TextDecorations;

var newAttributedText = nativeLabel.AttributedText != null ? new NSMutableAttributedString(nativeLabel.AttributedText) : new NSMutableAttributedString(label?.Text ?? string.Empty);
var strikeThroughStyleKey = UIStringAttributeKey.StrikethroughStyle;
var underlineStyleKey = UIStringAttributeKey.UnderlineStyle;

var range = new NSRange(0, newAttributedText.Length);

if ((textDecorations & TextDecorations.Strikethrough) == 0)
newAttributedText.RemoveAttribute(strikeThroughStyleKey, range);
else
newAttributedText.AddAttribute(strikeThroughStyleKey, NSNumber.FromInt32((int)NSUnderlineStyle.Single), range);

if ((textDecorations & TextDecorations.Underline) == 0)
newAttributedText.RemoveAttribute(underlineStyleKey, range);
else
newAttributedText.AddAttribute(underlineStyleKey, NSNumber.FromInt32((int)NSUnderlineStyle.Single), range);

nativeLabel.AttributedText = newAttributedText;
}
}
}
34 changes: 34 additions & 0 deletions src/Core/src/Platform/iOS/SearchBarExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,39 @@ public static void UpdatePlaceholder(this UISearchBar uiSearchBar, ISearchBar se
{
uiSearchBar.Placeholder = searchBar.Placeholder;
}

public static void UpdateFont(this UISearchBar uiSearchBar, ISearchBar searchBar, IFontManager fontManager)
{
uiSearchBar.UpdateFont(searchBar, fontManager, null);
}

public static void UpdateFont(this UISearchBar uiSearchBar, ISearchBar searchBar, IFontManager fontManager, UITextField? textField)
{
textField ??= uiSearchBar.FindDescendantView<UITextField>();

if (textField == null)
return;

var uiFont = fontManager.GetFont(searchBar.Font);
textField.Font = uiFont;
}

//public static void UpdateHorizontalTextAlignment(this UISearchBar uiSearchBar, ISearchBar searchBar)
//{
// UpdateHorizontalTextAlignment(uiSearchBar, searchBar, null);
//}

//public static void UpdateHorizontalTextAlignment(this UISearchBar uiSearchBar, ISearchBar searchBar, UITextField? textField)
//{
// textField ??= uiSearchBar.FindDescendantView<UITextField>();

// if (textField == null)
// return;

// // We don't have a FlowDirection yet, so there's nothing to pass in here.
// // TODO: Update this when FlowDirection is available
// // (or update the extension to take an ILabel instead of an alignment and work it out from there)
// textField.TextAlignment = searchBar.HorizontalTextAlignment.ToNative(true);
//}
}
}
8 changes: 8 additions & 0 deletions src/Core/src/Platform/iOS/TextFieldExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,13 @@ public static void UpdateCharacterSpacing(this UITextField textField, ISearchBar

// TODO: Include AttributedText to Label Placeholder
}

public static void UpdateFont(this UITextField textField, ISearchBar searchBar, IFontManager fontManager)
{
var uiFont = fontManager.GetFont(searchBar.Font);
textField.Font = uiFont;

textField.UpdateCharacterSpacing(searchBar);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,38 @@ Android.Views.TextAlignment GetNativeTextAlignment(SearchBarHandler searchBarHan
var editText = searchView.GetChildrenOfType<EditText>().First();
return editText.TextAlignment;
}

double GetNativeUnscaledFontSize(SearchBarHandler searchBarHandler)
{
var searchView = GetNativeSearchBar(searchBarHandler);
var editText = searchView.GetChildrenOfType<EditText>().FirstOrDefault();

if (editText == null)
return -1;

return editText.TextSize / editText.Resources.DisplayMetrics.Density;
}

bool GetNativeIsBold(SearchBarHandler searchBarHandler)
{
var searchView = GetNativeSearchBar(searchBarHandler);
var editText = searchView.GetChildrenOfType<EditText>().FirstOrDefault();

if (editText == null)
return false;

return editText.Typeface.IsBold;
}

bool GetNativeIsItalic(SearchBarHandler searchBarHandler)
{
var searchView = GetNativeSearchBar(searchBarHandler);
var editText = searchView.GetChildrenOfType<EditText>().FirstOrDefault();

if (editText == null)
return false;

return editText.Typeface.IsItalic;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,38 @@ public async Task PlaceholderInitializesCorrectly()

await ValidatePropertyInitValue(searchBar, () => searchBar.Placeholder, GetNativePlaceholder, searchBar.Placeholder);
}

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

await ValidatePropertyInitValue(searchBar, () => searchBar.Font.FontSize, GetNativeUnscaledFontSize, searchBar.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 searchBar = new SearchBarStub()
{
Text = "Test",
Font = Font.OfSize("Arial", 10).WithAttributes(attributes)
};

await ValidatePropertyInitValue(searchBar, () => searchBar.Font.FontAttributes.HasFlag(FontAttributes.Bold), GetNativeIsBold, isBold);
await ValidatePropertyInitValue(searchBar, () => searchBar.Font.FontAttributes.HasFlag(FontAttributes.Italic), GetNativeIsItalic, isItalic);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,5 +86,38 @@ double GetNativeCharacterSpacing(SearchBarHandler searchBarHandler)

return textField.AttributedText.GetCharacterSpacing();
}

double GetNativeUnscaledFontSize(SearchBarHandler searchBarHandler)
{
var uiSearchBar = GetNativeSearchBar(searchBarHandler);
var textField = uiSearchBar.FindDescendantView<UITextField>();

if (textField == null)
return -1;

return textField.Font.PointSize;
}

bool GetNativeIsBold(SearchBarHandler searchBarHandler)
{
var uiSearchBar = GetNativeSearchBar(searchBarHandler);
var textField = uiSearchBar.FindDescendantView<UITextField>();

if (textField == null)
return false;

return textField.Font.FontDescriptor.SymbolicTraits.HasFlag(UIFontDescriptorSymbolicTraits.Bold);
}

bool GetNativeIsItalic(SearchBarHandler searchBarHandler)
{
var uiSearchBar = GetNativeSearchBar(searchBarHandler);
var textField = uiSearchBar.FindDescendantView<UITextField>();

if (textField == null)
return false;

return textField.Font.FontDescriptor.SymbolicTraits.HasFlag(UIFontDescriptorSymbolicTraits.Italic);
}
}
}
6 changes: 5 additions & 1 deletion src/Core/tests/DeviceTests/Stubs/SearchBarStub.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ public partial class SearchBarStub : StubBase, ISearchBar

public string Placeholder { get; set; }

public TextAlignment HorizontalTextAlignment { get; set; }
public Color TextColor { get; set; }

public double CharacterSpacing { get; set; }

public Font Font { get; set; }

public TextAlignment HorizontalTextAlignment { get; set; }
}
}

0 comments on commit 6ec9b0e

Please sign in to comment.