根据需要从Web加载字体

时间:2016-05-27 23:51:03

标签: xamarin.forms custom-font ondemand

我想让用户在我的xamarin表单应用程序中选择字体。我有大约16个大小约10 MB的字体,我的应用程序大小太大,这将导致更大的尺寸。无论如何我可以在用户想要更改字体时下载字体吗?请帮忙。

1 个答案:

答案 0 :(得分:1)

我已经创建了一个完全符合您需求的样本。您可以找到源代码HERE。让我解释一下我所做的事情。

从架构的角度来看,我们需要做以下事情

  1. 从后端下载字体文件

  2. 在设备上缓存这些文件

  3. 确保它们适用于iOS和Android。在这一步中,我们需要进行一些特定于设备的调整以使字体工作。对于iOS,我们需要在iOS运行时注册字体。对于Android,我们需要为我们想要使用自定义字体的控件创建自定义渲染器。进一步了解详情。

  4. 演示ViewModel和View以演示功能。

  5. 从代码的角度来看,我已经完成了以下实现上述架构

    创建加载字体的服务

    IFontService - 在本地设备上下载和安装字体的服务

    public interface IFontService
        {
            //Directory where we'll keep custom fonts
            IFolder FontFolder { get; }
            //Contains mapping between font name and font file
            Dictionary<string, string> Fonts { get; }
            //Will download and install custom fonts and instantiate the Fonts mapping property
            Task LoadAvailableFonts();
        }
    

    实施IFontService

    BaseFontService - 实现IFontService的大部分内容,而不是特定于设备的。它有两个抽象方法,应该实现特定于缓存和安装字体的设备。

            //We will cache all the fonts in caches folder, which is device specific, 
            //That's why we use abstract property which we'll implement separately for iOS and android
            //and inject into PCL using dependency injection
            protected abstract Task<IFolder> GetCacheFolder();
    
            //For iOS we need to register custom fonts with iOS runtime. 
            //Check FontService implementation for more details.
            protected abstract Task InstallFonts(IEnumerable<CustomFont> fonts);
    

    实施特定于设备的内容并使用依赖注入

    在iOS和Android项目中,我创建了FontService实现,它源自BaseFontService并实现了特定于设备的逻辑 - 字体安装和缓存。

    <强> 的Android

    对于Android,我们只需要覆盖GetCacheFolder(),我们不需要为Android安装额外的步骤,这就是为什么我们可以将InstallFonts()实施留空。

    我们需要Android的另一个调整是我们想要使用自定义字体的那些控件的自定义渲染器。在iOS中,不需要此步骤,因为当您注册字体时,您可以在应用程序周围使用它们。在我的示例中,我创建了ButtonRendererLabelRenderer。他们只是听取FontFamily属性的更改,然后尝试使用IFontService找到该字体。我创建了一个FontToolbox类,它在TryGetFont方法中实现字体加载逻辑。如果要支持其他控件的自定义字体,可以使用与Button / Label渲染器中类似的模式,并使用TryGetFont加载实际字体。

    <强> 的iOS

    对于iOS来说,它有点复杂。我们需要从缓存目录加载字体文件并使用ios字体管理API注册它们。有关详细信息,请参阅here

    演示代码

    我创建了FontDemoViewModel,它将调用IFontService,将可用字体加载到我们视图中绑定的集合中。  我创建了FontDemoPage,允许从选择器中选择一种字体(我已添加BindablePickerEx控件)并更新按钮和标签的字体。

    一些注释

    确保字体文件名与字体的PostScript名称匹配。这不是Android所必需的,因为Android将能够加载具有任意名称的字体,因为它只需要对字体文件的引用。但是对于iOS,您需要确保这是真的,因为运行时通过其PostScript名称搜索字体。 Here您可以找到如何获取字体的PostScript名称。

    另一件事是,为了简单起见,在此示例中,我已将所有字体嵌入到汇编资源中。在我的BaseFontService中,我在此方法中加载了程序集资源中的所有字体

    private async Task<List<CustomFont>> DownloadFonts()
    

    对于您的实施,您需要在此处发出实际的网络请求,以便从后端下载字体。