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

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

目录
相关文章
|
10天前
|
iOS开发 UED
实现一个自定义的iOS动画效果
【4月更文挑战第9天】本文将详细介绍如何在iOS平台上实现一个自定义的动画效果。我们将通过使用Core Animation框架来实现这个动画效果,并展示如何在不同的场景中使用它。文章的目标是帮助读者理解如何使用Core Animation框架来创建自定义动画,并提供一个简单的示例代码。
13 1
|
前端开发
实例|APICloud AVM框架封装滑动单元格组件
滑动单元格组件原理是主题部分把按钮进行遮挡,按钮通过绝对定位,定位在最右边,通过监听触摸事件(touch),判断滑动的方向和计算滑动的距离以此来判定显示和隐藏按钮。
148 0
SwiftUI直通车系列(5)—— 自定义绘制
SwiftUI直通车系列(5)—— 自定义绘制
127 0
SwiftUI直通车系列(5)—— 自定义绘制
SwiftUI直通车系列(5)—— 自定义绘制(二)
SwiftUI直通车系列(5)—— 自定义绘制
132 0
SwiftUI直通车系列(5)—— 自定义绘制(二)
|
iOS开发 开发者
iOS开发CoreGraphics核心图形框架之四——变换函数
iOS开发CoreGraphics核心图形框架之四——变换函数
130 0
第二十七章:自定义渲染器(六)
有趣的是,Android SeekBar小部件具有与Steps属性等效的功能,但不等同于Minimum和Maximum属性! 这怎么可能? SeekBar实际上定义了一个名为Max的整数属性,SeekBar的Progress属性始终是一个从0到Max的整数。
734 0
|
Windows
第二十七章:自定义渲染器(五)
渲染器和事件(1) 大多数Xamarin.Forms元素都是交互式的。他们通过触发事件来响应用户输入。如果在Xamarin.Forms自定义元素中实现事件,则可能还需要在呈现器中为本机控件触发的相应事件定义事件处理程序。
685 0
|
前端开发 Android开发 iOS开发
第二十七章:自定义渲染器(四)
渲染器和属性(2) 现在,对于iOS,EllipseUIView类是存在的,可以使用EllipseUIView作为本机控件来编写EllipseViewRenderer。 从结构上讲,这个类几乎与Windows渲染器相同: using System.
549 0
|
Android开发 iOS开发 Windows
第二十七章:自定义渲染器(三)
渲染器和属性(1) Xamarin.Forms包含一个BoxView元素,用于显示矩形颜色块。 你有没有希望你有类似的东西画一个圆圈,或使它更通用,椭圆?这就是EllipseView的目的。 但是,因为您可能希望在多个应用程序中使用EllipseView,所以它在第20章“异步和文件I / O”中介绍的Xamarin.FormsBook.Platform库中实现。
756 0