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

简介: 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平台的渲染器。
我们来试试吧!

目录
相关文章
|
6月前
|
存储
CocosCreator3.8研究笔记(二十二)CocosCreator 动画系统-动画剪辑和动画组件介绍
CocosCreator3.8研究笔记(二十二)CocosCreator 动画系统-动画剪辑和动画组件介绍
111 0
|
11天前
|
iOS开发 UED
实现一个自定义的iOS动画效果
【4月更文挑战第9天】本文将详细介绍如何在iOS平台上实现一个自定义的动画效果。我们将通过使用Core Animation框架来实现这个动画效果,并展示如何在不同的场景中使用它。文章的目标是帮助读者理解如何使用Core Animation框架来创建自定义动画,并提供一个简单的示例代码。
13 1
|
3月前
|
JavaScript atlas Kotlin
深度解读dragonBones使用SpriteFrame任意换肤的实现
深度解读dragonBones使用SpriteFrame任意换肤的实现
44 0
|
4月前
|
前端开发
自定义elementUI皮肤、色系、主题、主色调
自定义elementUI皮肤、色系、主题、主色调
|
9月前
|
JavaScript 定位技术
WebGis——Pixi开发vue项目之使用遮罩实现图形缓慢填充颜色(三)
WebGis——Pixi开发vue项目之使用遮罩实现图形缓慢填充颜色(三)
|
前端开发 JavaScript UED
封装库/工具库中重要概念之动画
前端开发中,动画是一个非常重要的技术特性。它可以提升用户体验,增加页面交互性,并且让网站看起来更加生动活泼。然而,在实现复杂动画时,手写代码往往会变得繁琐且容易出错。因此,前端工具库和封装库的出现为我们提供了便利。在本文中,我们将探讨前端中的封装库和工具库以及它们在实现动画效果方面的作用。
74 0
|
API 数据库 开发者
用HarmonyOS ArkUI调用三方库PhotoView实现图片的联播、缩放
本文演示如果用HarmonyOS的ArkUI来调用已经上架到三方库中心的社区库。体验HarmonyOS 3最新的API 9,欢迎大家一起参与构建这个万物互联的时代
147 0
|
iOS开发 开发者
iOS开发CoreGraphics核心图形框架之六——梯度渐变(一)
iOS开发CoreGraphics核心图形框架之六——梯度渐变
245 0
iOS开发CoreGraphics核心图形框架之六——梯度渐变(一)
第二十七章:自定义渲染器(六)
有趣的是,Android SeekBar小部件具有与Steps属性等效的功能,但不等同于Minimum和Maximum属性! 这怎么可能? SeekBar实际上定义了一个名为Max的整数属性,SeekBar的Progress属性始终是一个从0到Max的整数。
734 0
|
Windows
第二十七章:自定义渲染器(五)
渲染器和事件(1) 大多数Xamarin.Forms元素都是交互式的。他们通过触发事件来响应用户输入。如果在Xamarin.Forms自定义元素中实现事件,则可能还需要在呈现器中为本机控件触发的相应事件定义事件处理程序。
685 0