- PVSM.RU - https://www.pvsm.ru -

Для отображения иконок в приложении Xamarin.Forms можно использовать изображения в различных форматах, например png, svg или шрифты ttf. Чаще всего для добавления стандартных иконок удобен шрифт с иконками, например google material icons. Шрифт с иконками имеет размер около 200КБ и удобство использования здесь обычно важнее экономии на размере приложения. Иконки будут хорошо смотреться при любом разрешении экрана и будут чёрно-белыми.
Для использования иконок есть готовые nuget-пакеты. Я долгое время использовал iconize (nuget — www.nuget.org/packages/Xam.Plugin.Iconize [1]; git — github.com/jsmarcus/Iconize [2]). Он позволяет подключать более десяти шрифтов, добавляет новые контролы, такие как IconButton, IconImage, IconLabel и т.п. Но тут есть обычные аргументы против готовых библиотек: лишний функционал, лишний размер файлов, не полностью устраивает поведение, баги и т.п. Поэтому в определённый момент решил отказаться от готовой библиотеки и заменить ее на простейший велосипед из пары классов + шрифт.
Иконка из шрифта ttf используется в xaml следующим образом(iOS):
<Label Text="" FontFamily="MaterialIcons-Regular"/>
В C#:
var label = new Label { Text ="ue5d2", FontFamily = "MaterialIcons-Regular" };
Перечислю возникающие проблемы.
1. разный формат записи кода иконки в XAML и C# ("" / "ue5d2")
2. код иконки не ассоциируется с самой иконкой, хотелось бы использовать что-то вроде «arrow_back», как в iconize
3. если приложение будет работать на android и iOS, то по-разному надо писать название шрифта — «MaterialIcons-Regular.ttf#MaterialIcons-Regular» в андроид и «MaterialIcons-Regular» в iOS
Описываемое здесь решение требует наличия события TextChanged у элемента управления Label. Добавим и эту проблему в список:
4. у контрола Label отсутствует событие TextChanged. Это нам нужно, чтобы отслеживать изменения текста метки и использовать binding в xaml
Для примера возьмём шрифт google material icons. Сначала добавим его в андроид и iOS проекты.
Шрифт скачивать здесь [3]
Иконки искать здесь [4]
Скачиваем файл шрифта — MaterialIcons-Regular.ttf.
Android:
Добавляем MaterialIcons-Regular.ttf в папку Assets и выбираем ему «Build action» AndroidAsset.
iOS:
Добавляем MaterialIcons-Regular.ttf в папку ResourcesFonts и выбираем ему «Build action» BundleResource, затем прописываем шрифт в info.plist:
<key>UIAppFonts</key>
<array>
<string>Fonts/MaterialIcons-Regular.ttf</string>
</array>
Теперь предположим, мы хотим иконку со стрелкой влево в нашем приложении. Заходим на страницу с поисковиком иконок: https://material.io/resources/icons/ [4], вводим «arrow» в левом верхнем углу, выбираем стрелку влево в результатах. Теперь нажимаем на панель «Selected Icon» чтобы увидеть код иконки… а его там нет:
Usage:
<!--For modern browsers-->
<i class="material-icons">
arrow_back
</i>
<!-- For IE9 or below. -->
<i class="material-icons">
arrow_back
</i>
Да и не очень удобно каждый раз переводить названия в коды, а потом в коде приложения разбираться что это за иконка. Удобнее было бы использовать понятное имя иконки — «arrow_back» вот таким образом:
<Label Text="arrow_back">
Для решения будем использовать так называемые behavior, в русском переводе «Реакции на события Xamarin.Forms» (https://docs.microsoft.com/ru-ru/xamarin/xamarin-forms/app-fundamentals/behaviors/ [5])
Для этого создадим класс GoogleMaterialFontBehavior:
public class GoogleMaterialFontBehavior: BehaviorBase<CustomLabel>
{
}
Наш behavior будет реагировать на изменение текста метки, поэтому придётся также доработать Label:
using System;
using Xamarin.Forms;
namespace MyApp.UserControls
{
public class CustomLabel : Label
{
public event EventHandler<EventArgs> TextChanged;
public static readonly new BindableProperty TextProperty =
BindableProperty.Create(
propertyName: nameof(Text),
returnType: typeof(string),
declaringType: typeof(CustomLabel),
defaultValue: "",
defaultBindingMode: BindingMode.OneWay,
propertyChanged: TextChangedHandler);
public new string Text
{
get => (string)GetValue(TextProperty);
set
{
base.Text = value;
SetValue(TextProperty, value);
}
}
private static void TextChangedHandler(BindableObject bindable, object oldValue, object newValue)
{
var control = bindable as CustomLabel;
control.TextChanged?.Invoke(control, new EventArgs());
}
}
}
В классе GoogleMaterialFontBehavior надо:
namespace MyApp.Behaviors
{
public class GoogleMaterialFontBehavior: BehaviorBase<CustomLabel>
{
protected override void OnAttachedTo(CustomLabel bindable)
{
HandleTextChanged(bindable, null);
bindable.TextChanged += HandleTextChanged;
base.OnAttachedTo(bindable);
}
protected override void OnDetachingFrom(CustomLabel bindable)
{
bindable.TextChanged -= HandleTextChanged;
base.OnDetachingFrom(bindable);
}
private void HandleTextChanged(object sender, EventArgs e)
{
var label = (CustomLabel)sender;
if (label?.Text?.Length >= 2
&& iconCodeDict.TryGetValue(label.Text, out var icon))
{
label.FontFamily = fontFamily;
label.Text = icon.ToString();
}
}
//
private static readonly string fontFamily = Device.RuntimePlatform == Device.Android ? "MaterialIcons-Regular.ttf#MaterialIcons-Regular" : "MaterialIcons-Regular";
private static readonly Dictionary<string, char> iconCodeDict = new Dictionary<string, char>
{
{"3d_rotation", 'ue84d'},
{"ac_unit", 'ueb3b'},
{"access_alarm", 'ue190'},
…
}
}
}
А теперь про сам справочник iconCodeDict. Он будет содержать пары имя-код для символов шрифта. В случае с google material icons эти данные лежат в git-репозитории в отдельном файле: github.com/google/material-design-icons/blob/master/iconfont/codepoints [6]
XAML:
в начале страницы добавить 2 неймспейса:
xmlns:uc="clr-namespace:MyApp.UserControls"
xmlns:b="clr-namespace:MyApp.Behaviors"
и выводим иконку:
<uc:CustomLabel Text="arrow_back" FontSize="30">
<Label.Behaviors>
<b:GoogleMaterialFontBehavior />
</Label.Behaviors>
</uc:CustomLabel>
C#:
var label = new CustomLabel();
label.Behaviors.Add (new GoogleMaterialFontBehavior());
label.Text = "arrow_back";
Также мне очень понравился шрифт Jam icons. Для него создадим класс JamFontBehavior по аналогии с GoogleMaterialFontBehavior. Другими в нём будут: fontFamily и iconCodeDict.
Шрифт скачивать здесь: https://github.com/michaelampr/jam/blob/master/fonts/jam-icons.ttf [7]
Иконки искать здесь: https://jam-icons.com/ [8]
Очень удобный поисковик. Находите иконку, жмёте на нее и имя в буфере обмена. Осталось просто вставить его в код.
Алгоритм такой же, как для иконок от google, кроме получения кодов иконок.
Коды надо взять из файла svg, находящегося там же [9].
Данные легко вытащить при помощи текстового редактора, например sublime. Выделяете строку «data-tags», нажимаете Alt+F3, включается мультикурсор. Далее shift+home, ctrl+c, ctrl+a, ctrl+v. И так далее. Можно при помощи Excel, кому что привычнее.
Например, стрелка влево выглядит в svg-файле так:
<glyph unicode="" glyph-name="arrow-left" data-tags="arrow-left" d="M358.997 398.635l168.533-168.533c7.15-7.611 11.543-17.885 11.543-29.185 0-23.564-19.103-42.667-42.667-42.667-11.311 0-21.594 4.401-29.229 11.585l0.022-0.020-241.365 241.323c-7.749 7.706-12.545 18.376-12.545 30.165s4.796 22.459 12.544 30.163l241.367 241.367c7.769 8.036 18.647 13.026 30.69 13.026 23.564 0 42.667-19.103 42.667-42.667 0-12.043-4.989-22.92-13.014-30.678l-168.545-168.545h409.003c23.564 0 42.667-19.103 42.667-42.667s-19.103-42.667-42.667-42.667v0h-409.003z" />
После очистки текста получаем содержимое полей glyph-name и unicode:
{"arrow-left", 'ue92b'}
и добавляем в словарь iconCodeDict
Автор: aleks42
Источник [10]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/krossplatformennaya-razrabotka/330028
Ссылки в тексте:
[1] www.nuget.org/packages/Xam.Plugin.Iconize: https://www.nuget.org/packages/Xam.Plugin.Iconize/
[2] github.com/jsmarcus/Iconize: https://github.com/jsmarcus/Iconize
[3] Шрифт скачивать здесь: https://github.com/google/material-design-icons/blob/master/iconfont/MaterialIcons-Regular.ttf
[4] Иконки искать здесь: https://material.io/resources/icons/
[5] https://docs.microsoft.com/ru-ru/xamarin/xamarin-forms/app-fundamentals/behaviors/: https://docs.microsoft.com/ru-ru/xamarin/xamarin-forms/app-fundamentals/behaviors/
[6] github.com/google/material-design-icons/blob/master/iconfont/codepoints: https://github.com/google/material-design-icons/blob/master/iconfont/codepoints
[7] https://github.com/michaelampr/jam/blob/master/fonts/jam-icons.ttf: https://github.com/michaelampr/jam/blob/master/fonts/jam-icons.ttf
[8] https://jam-icons.com/: https://jam-icons.com/
[9] там же: https://raw.githubusercontent.com/michaelampr/jam/master/fonts/jam-icons.svg
[10] Источник: https://habr.com/ru/post/467423/?utm_source=habrahabr&utm_medium=rss&utm_campaign=467423
Нажмите здесь для печати.