第二十七章:自定义渲染器(一)

简介: Xamarin.Forms的核心可能看起来很神奇:像Button这样的单个元素在iOS,Android和Windows操作系统下显示为本机按钮的能力。在本章中,您将看到如何在所有三个平台上的Xamarin.Forms中的每个元素都由称为渲染器的特殊类支持。

Xamarin.Forms的核心可能看起来很神奇:像Button这样的单个元素在iOS,Android和Windows操作系统下显示为本机按钮的能力。在本章中,您将看到如何在所有三个平台上的Xamarin.Forms中的每个元素都由称为渲染器的特殊类支持。例如,Xamarin.Forms中的Button类由各种平台中的几个类支持,每个类都名为ButtonRenderer。
好消息是你也可以编写自己的渲染器,本章将向你展示如何。但是,请记住,编写自定义渲染器是一个很大的主题,本章只能帮助您入门。
编写自定义渲染器并不像编写Xamarin.Forms应用程序那么容易。您需要熟悉各个iOS,Android和Windows运行时平台。但显然它是一种强大的技术。实际上,一些开发人员认为Xamarin.Forms的最终价值在于提供一个编写自定义渲染器的结构化框架。

完整的类层次结构

在第11章“可绑定基础结构”中,您看到了一个名为ClassHierarchy的程序,它显示了Xamarin.Forms类层次结构。 但是,该程序仅显示Xamarin.Forms.Core和Xamarin.Forms.Xaml程序集中的类型,这些程序集是Xamarin.Forms应用程序通常使用的类型。
Xamarin.Forms还包含与每个平台关联的其他程序集。 这些程序集通过为Xamarin.Forms提供平台支持(包括所有渲染器)起着至关重要的作用。
您可能已经熟悉了这些程序集的名称,可以在Xamarin.Forms解决方案的各个项目的Reference部分中看到它们:

  • Xamarin.Forms.Platform(非常小)
  • Xamarin.Forms.Platform.iOS
  • Xamarin.Forms.Platform.Android
  • Xamarin.Forms.Platform.UAP
  • Xamarin.Forms.Platform.WinRT(大于此列表中的下两个)
  • Xamarin.Forms.Platform.WinRT.Tablet
  • Xamarin.Forms.Platform.WinRT.Phone

在本讨论中,这些将统称为平台组件。
是否可以编写一个Xamarin.Forms应用程序,在这些平台程序集中显示类型的类层次结构?
是! 但是,如果您仅限于检查通常使用应用程序加载的程序集 - 这当然是最简单的方法 - 那么应用程序只能显示属于该应用程序的程序集中的类型。 例如,您只能使用在iOS下运行的Xamarin.Forms程序在Xamarin.Forms.Platform.iOS程序集中显示类型,对于其他程序集也是如此。
但是仍然存在一个问题:您可能还记得,最初的ClassHierarchy程序首先是根据它知道的两个类(View和Extensions)获取Xamarin.Forms.Core和Xamarin.Forms.Xaml程序集的.NET程序集对象。 在这两个集会中:

typeof(View).GetTypeInfo().Assembly
typeof(Extensions).GetTypeInfo().Assembly

但是,Xamarin.Forms应用程序的可移植类库无法直接访问平台程序集。 平台程序集仅由应用程序项目引用。 这意味着Xamarin.Forms可移植类库不能使用类似的代码来获取对平台程序集的引用。 这不起作用:

typeof(ButtonRenderer).GetTypeInfo().Assembly

但是,这些平台程序集在应用程序运行时会加载,因此PCL可以根据程序集名称获取平台程序集的Assembly对象。 PlatformClassHierarchy程序如下所示:

public partial class PlatformClassHierarchyPage : ContentPage
{
    public PlatformClassHierarchyPage()
    {
        InitializeComponent();
        List<TypeInformation> classList = new List<TypeInformation>();
        string[] assemblyNames = Device.OnPlatform(
        iOS: new string[] { "Xamarin.Forms.Platform.iOS" },
        Android: new string[] { "Xamarin.Forms.Platform.Android" },
        WinPhone: new string[] { "Xamarin.Forms.Platform.UAP",
                                 "Xamarin.Forms.Platform.WinRT",
                                 "Xamarin.Forms.Platform.WinRT.Tablet",
                                 "Xamarin.Forms.Platform.WinRT.Phone" }
        );
        foreach (string assemblyName in assemblyNames)
        {
            try
            {
                Assembly assembly = Assembly.Load(new AssemblyName(assemblyName));
                GetPublicTypes(assembly, classList);
            }
            catch
            {
            }
        }
        __
}

从那里,PlatformClassHierarchy程序与原始的ClassHierarchy程序相同。
如您所见,foreach循环从静态Assembly.Load方法获取Assembly对象。 但是,程序无法直接确定它是在通用Windows平台还是其他Windows运行时平台下运行,因此如果Device.OnPlatform指示它是WinPhone设备,程序将尝试所有四个程序集并使用try 并抓住只是忽略那些不起作用的。
一些类名 - 特别是程序集外部类的完全限定类名 - 对于纵向显示而言有点太长并且包装不好,但这是三个平台上显示的一部分。 每个都已滚动到以通用ViewRenderer类开头的类层次结构的一部分。 这通常是您创建自己的自定义渲染器的类:
2019_05_31_094420
注意ViewRenderer类的通用参数,名为TView和TNativeView,或TElement和TNativeElement:正如您将看到的,TView或TElement是Xamarin.Forms元素,如Button,而TNativeView或TNativeElement是该Button的本机控件。。
虽然PlatformClassHierarchy程序没有指明这一点,但ViewRenderer泛型参数的约束依赖于平台:

  • 在iOS上:
  1. TView受限于Xamarin.Forms.View

o TNativeView受限于UIKit.UIView

  • 在Android上:
  1. TView受限于Xamarin.Forms.View

o TNativeView受限于Android.Views.View

  • 在Windows平台上:
  1. TElement受限于Xamarin.Forms.View

o TNativeElement受限于Windows.UI.Xaml.FrameworkElement

要编写自定义渲染器,可以从ViewRenderer派生一个类。 要适应所有平台,您必须使用从UIView派生的类来实现iOS渲染器,使用从View派生的类实现Android渲染器,并使用派生自FrameworkElement的类实现Windows平台的渲染器。
我们来试试吧!

目录
相关文章
|
前端开发 JavaScript 开发者
别再只用普通函数了!箭头函数的四大神奇区别,让你的代码飞起来!
【8月更文挑战第23天】在Web前端开发中,JavaScript的箭头函数(引入于ES6)提供了一种比传统函数更加简洁的定义方法。箭头函数使用 &quot;=&gt;&quot; 替代 &quot;function&quot; 关键字,并且自动绑定外部 &quot;this&quot; 上下文,避免了传统函数中 &quot;this&quot; 值因调用方式不同而变化的问题。此外,箭头函数不拥有自己的 &quot;arguments&quot; 对象,但可以通过剩余参数语法获取所有参数。需要注意的是,箭头函数不能作为构造函数使用。理解这些差异有助于开发者编写更高效、清晰的代码。
596 0
|
Go
Golang语言之包依赖管理
这篇文章详细介绍了Go语言的包依赖管理工具,包括godep和go module的使用,以及如何在项目中使用go module进行依赖管理,还探讨了如何导入本地包和第三方库下载的软件包存放位置。
336 4
|
缓存 算法 数据安全/隐私保护
计算机网络(3)----介质访问控制
计算机网络(3)----介质访问控制
663 1
|
11月前
|
XML API 开发者
探究获取亚马逊畅销榜API接口及实战应用
亚马逊MWS(商城网络服务)提供了一系列API接口,帮助开发者获取平台数据,其中畅销榜API尤为关键。通过注册开发者账号、创建应用并申请权限,可使用HTTP POST请求获取商品的销售排名、价格等信息。Python代码示例展示了如何构建和发送请求,并处理返回的XML或JSON数据。注意遵守亚马逊的频率限制、数据准确性和合规性要求,以确保安全合法地利用这些数据支持电商业务决策。
416 1
|
机器学习/深度学习 边缘计算 PyTorch
PyTorch 与 ONNX:模型的跨平台部署策略
【8月更文第27天】深度学习模型的训练通常是在具有强大计算能力的平台上完成的,比如配备有高性能 GPU 的服务器。然而,为了将这些模型应用到实际产品中,往往需要将其部署到各种不同的设备上,包括移动设备、边缘计算设备甚至是嵌入式系统。这就需要一种能够在多种平台上运行的模型格式。ONNX(Open Neural Network Exchange)作为一种开放的标准,旨在解决模型的可移植性问题,使得开发者可以在不同的框架之间无缝迁移模型。本文将介绍如何使用 PyTorch 将训练好的模型导出为 ONNX 格式,并进一步探讨如何在不同平台上部署这些模型。
1455 2
|
网络协议 Unix Linux
网安人必须人手一份的《Linux私房教程》,GitHub星标286K!
Linux是一套免费使用和自由传播的操作系统内核,是一个基于POSIX和Unix的多用户、多任务支持多线程和多CPU的操作系统内核。它能运行主要的Unix工具软件、应用程序和网络协议。它支持32位和64位硬件。Linux继承了Unix以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统内核。 作为网络安全的初学者,Linux基础知识和常用命令是我们的必备技能,我们不能只会操作Windows相关的工具。一方面很多网站都是基于Linux环境搭建,比如LAMP,其安全性更好;另一方面,很多命令或工具都集成在了Linux相关环境中,比如Kali等。 今天给小伙伴们分享一份Linux私房教程,这份
|
程序员
时序预测 | MATLAB实现基于KNN K近邻的时间序列预测-递归预测未来(多指标评价)
时序预测 | MATLAB实现基于KNN K近邻的时间序列预测-递归预测未来(多指标评价)
|
传感器 机器学习/深度学习 自动驾驶
自动驾驶中的感知模型:实现安全和智能驾驶的关键
自动驾驶中的感知模型:实现安全和智能驾驶的关键
410 9
|
监控 前端开发 Java
spring mvc 获取请求参数,获取返回值的解决办法
spring mvc 获取请求参数,获取返回值的解决办法
452 0
|
负载均衡 算法
SpringCloud&Ribbon负载均衡原理与实践
SpringCloud&Ribbon负载均衡原理与实践
255 3