Xamarin.Forms - uso conveniente de fontes de ícone no aplicativo


Declaração do problema


Você pode usar imagens em vários formatos, por exemplo, fontes png, svg ou ttf, para exibir ícones no aplicativo Xamarin.Forms. Na maioria das vezes, uma fonte com ícones é conveniente para adicionar ícones padrão, por exemplo, ícones de materiais do google. A fonte com ícones tem um tamanho de cerca de 200K e a usabilidade geralmente é mais importante do que economizar no tamanho do aplicativo. Os ícones terão boa aparência em qualquer resolução de tela e ficarão em preto e branco.

Existem pacotes de pepitas prontos para usar ícones. Eu usei iconize por um longo tempo (nuget - www.nuget.org/packages/Xam.Plugin.Iconize ; git - github.com/jsmarcus/Iconize ). Permite conectar mais de dez fontes, adicionar novos controles, como IconButton, IconImage, IconLabel, etc. Mas aqui estão os argumentos usuais contra bibliotecas prontas: funcionalidade extra, tamanho extra de arquivo, não completamente satisfeito com o comportamento, bugs, etc. Portanto, em algum momento, decidi abandonar a biblioteca concluída e substituí-la por uma bicicleta simples de um par de classes + fonte.

O ícone da fonte ttf é usado no xaml da seguinte forma (iOS):

<Label Text="&#xe5d2;" FontFamily="MaterialIcons-Regular"/> 

Em c #:

 var label = new Label { Text ="\ue5d2", FontFamily = "MaterialIcons-Regular" }; 

Vou listar os problemas que surgirem.

1. formato diferente para escrever o código do ícone em XAML e C # ("& # xe5d2;" / "\ ue5d2")

2. o código do ícone não está associado ao próprio ícone, eu gostaria de usar algo como "arrow_back", como em iconize

3. Se o aplicativo for executado no Android e iOS, você precisará escrever o nome da fonte de maneira diferente - “MaterialIcons-Regular.ttf # MaterialIcons-Regular” no android e “MaterialIcons-Regular” no iOS

A solução descrita aqui requer o evento TextChanged no controle Label. Adicione este problema à lista:

4. o controle Label não possui um evento TextChanged. Precisamos disso para rastrear alterações no texto do rótulo e usar a ligação no xaml

Solução


Por exemplo, use os ícones de materiais do google para fontes. Primeiro, adicione-o aos projetos Android e iOS.
Faça o download da fonte aqui
Pesquisa de ícones aqui

Faça o download do arquivo da fonte - MaterialIcons-Regular.ttf.

Android:
Adicione MaterialIcons-Regular.ttf à pasta Assets e selecione o AndroidAsset "Ação de compilação".

iOS:
Adicione MaterialIcons-Regular.ttf à pasta Resources \ Fonts e selecione a opção "Build action" BundleResource, depois escreva a fonte em info.plist:

 <key>UIAppFonts</key> <array> <string>Fonts/MaterialIcons-Regular.ttf</string> </array> 

Agora, suponha que desejemos um ícone de seta esquerda em nosso aplicativo. Vamos para a página com o ícone do mecanismo de busca: https://material.io/resources/icons/ , digite "seta" no canto superior esquerdo, selecione a seta esquerda nos resultados. Agora clique no painel "Ícone selecionado" para ver o código do ícone ... mas ele não está lá:

 Usage: <!--For modern browsers--> <i class="material-icons"> arrow_back </i> <!-- For IE9 or below. --> <i class="material-icons"> arrow_back </i> 

Sim, e não é muito conveniente converter os nomes em códigos a cada vez e descobrir qual é o ícone no código do aplicativo. Seria mais conveniente usar o nome amigável do ícone - "arrow_back" assim:

 <Label Text="arrow_back"> 

Para a solução, usaremos o chamado comportamento na tradução russa de "Reações ao Xamarin.Forms Events" ( https://docs.microsoft.com/ru-ru/xamarin/xamarin-forms/app-fundamentals/behaviors/ )

Para fazer isso, crie a classe GoogleMaterialFontBehavior:

 public class GoogleMaterialFontBehavior: BehaviorBase<CustomLabel> { } 

Nosso comportamento responderá à alteração do texto do rótulo, portanto, o Label também precisará ser finalizado:

 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()); } } } 

Na classe GoogleMaterialFontBehavior, você precisa de:

  • substituir métodos OnAttachedTo / OnDetachingFrom
  • adicionar manipulador de alterações de texto: HandleTextChanged
  • adicionar nome da fonte fontFamily
  • e também adicione um diretório de códigos de caracteres iconCodeDict

 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'}, … } } } 

E agora sobre a referência iconCodeDict em si. Ele conterá pares nome-código para caracteres de fonte. No caso de ícones de materiais do google, esses dados estão em um repositório git em um arquivo separado: github.com/google/material-design-icons/blob/master/iconfont/codepoints

Exemplo de uso


XAML:

no topo da página, adicione 2 espaços para nome:

 xmlns:uc="clr-namespace:MyApp.UserControls" xmlns:b="clr-namespace:MyApp.Behaviors" 

e exiba o ícone:

 <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"; 

Opcional


Eu também gostei muito dos ícones de fontes Jam. Vamos criar uma classe JamFontBehavior para ela, semelhante ao GoogleMaterialFontBehavior. Outros nele serão: fontFamily e iconCodeDict.

Baixe a fonte aqui: https://github.com/michaelampr/jam/blob/master/fonts/jam-icons.ttf
Ícones para pesquisar aqui: https://jam-icons.com/

Motor de busca muito conveniente. Encontre o ícone, clique nele e no nome na área de transferência. Resta simplesmente inseri-lo no código.

O algoritmo é o mesmo que para os ícones do Google, exceto para obter códigos de ícones.

Os códigos devem ser retirados do arquivo svg localizado no mesmo local .

Os dados podem ser facilmente extraídos usando um editor de texto, como sublime. Selecione a linha "data-tags", pressione Alt + F3, o multi-cursor está ativado. Próximo turno + home, ctrl + c, ctrl + a, ctrl + v. E assim por diante É possível com a ajuda do Excel, a quem o que é mais familiar.

Por exemplo, a seta esquerda se parece com isso no arquivo svg:

 <glyph unicode="&#xe92b;" 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" /> 

Após limpar o texto, obtemos o conteúdo dos campos de nome do glifo e unicode:

 {"arrow-left", '\ue92b'} 

e adicione iconCodeDict ao dicionário

Source: https://habr.com/ru/post/pt467423/


All Articles