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

简介: 您好,自定义渲染器!HelloRenderers程序主要演示编写简单渲染器所需的开销。 该程序定义了一个名为HelloView的新View衍生,旨在显示一个简单的固定文本字符串。 这是HelloRenderers可移植类库项目中的完整HelloView.cs文件:using Xamarin.Forms;namespace HelloRenderers{ public class HelloView : View { }}而已! 但请注意,该类被定义为public。

您好,自定义渲染器!

HelloRenderers程序主要演示编写简单渲染器所需的开销。 该程序定义了一个名为HelloView的新View衍生,旨在显示一个简单的固定文本字符串。 这是HelloRenderers可移植类库项目中的完整HelloView.cs文件:

using Xamarin.Forms;
namespace HelloRenderers
{
    public class HelloView : View 
    {
    }
}

而已! 但请注意,该类被定义为public。 即使您可能认为此类仅在PCL中引用,但事实并非如此。 它必须对平台组件可见。
HelloRenderers PCL非常简单,甚至不会打扰页面类。 相反,它实例化并在App.cs文件中显示以页面为中心的HelloView对象:

namespace HelloRenderers
{
    public class App : Application
    {
        public App()
        {
            MainPage = new ContentPage
            {
                Content = new HelloView
                {
                    VerticalOptions = LayoutOptions.Center,
                    HorizontalOptions = LayoutOptions.Center
                }
            };
        }
    __
    }
}

没有任何其他代码,这个程序运行正常,但你实际上不会在屏幕上看到HelloView对象,因为它只是一个空白的透明视图。 我们需要的是HelloView的一些平台渲染器。
当Xamarin.Forms应用程序启动时,Xamarin.Forms使用.NET反射搜索构成应用程序的各种程序集,查找名为ExportRenderer的程序集属性。 ExportRenderer属性指示是否存在可以为Xamarin.Forms元素提供支持的自定义渲染器。
HelloRenderers.iOS项目包含以下HelloViewRenderer.cs文件,完整显示。 请注意using指令下的ExportRenderer属性。 因为这是一个程序集属性,所以它必须在名称空间声明之外。 这个特殊的ExportRenderer属性基本上表示“HelloViewRenderer类型的渲染器支持HelloView类”:

using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using UIKit;
using HelloRenderers;
using HelloRenderers.iOS;
[assembly: ExportRenderer(typeof(HelloView), typeof(HelloViewRenderer))]
namespace HelloRenderers.iOS
{
    public class HelloViewRenderer : ViewRenderer<HelloView, UILabel>
    {
        protected override void OnElementChanged(ElementChangedEventArgs<HelloView> args)
        {
            base.OnElementChanged(args);
            if (Control == null)
            {
                UILabel label = new UILabel
                {
                    Text = "Hello from iOS!",
                    Font = UIFont.SystemFontOfSize(24)
                };
                SetNativeControl(label);
            }
        }
    }
}

HelloViewRenderer类的定义遵循ExportRenderer属性。这堂课必须公开。它派生自通用的ViewRenderer类。这两个通用参数名为TView,它是Xamarin.Forms类,TNativeView是这个特殊情况下的类,是iOS的原生类。
在iOS中,显示文本的类是UIKit名称空间中的UILabel,这就是这里使用的内容。 ViewRenderer的两个泛型参数基本上说“一个HelloView对象实际上被渲染为iOS UILabel对象”。
ViewRenderer派生的一个基本工作是覆盖OnElementChanged方法。创建HelloView对象时调用此方法,其作用是创建用于呈现HelloView对象的本机控件。
OnElementChanged覆盖首先检查该类是否继承自ViewRenderer的Control属性。此Control属性由ViewRenderer定义为TNativeView类型,因此在HelloViewRenderer中它的类型为UILabel。第一次调用OnElementChanged时,此Control属性将为null。必须创建UILabel对象。这就是该方法的作用,为其分配一些文本和字体大小。然后将该UILabel方法传递给SetNativeControl方法。此后,Control属性将是此UILabel对象。
文件顶部的using指令分为三组:

  • ExportRenderer属性需要Xamarin.Forms命名空间的using指令,而ViewRenderer类需要Xamarin.Forms.Platform.iOS。
  • UILabel需要iOS UIKIt名称空间。
  • 仅对于ExportRenderer属性中的HelloView和HelloViewRenderer引用,需要HelloRenderers和HelloRenderers.iOS的using指令,因为该属性必须位于HelloRenderer.iOS命名空间块之外。

最后两个使用指令特别烦人,因为它们只需要一个目的。 如果您愿意,可以通过完全限定ExportRenderer属性中的类名来删除这两个使用指令。
这在以下渲染器中完成。 这是HelloRenderers.Droid项目中的完整HelloViewRenderer.cs文件。 用于显示文本的Android小部件是Android.Widget命名空间中的TextView:

using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using Android.Util;
using Android.Widget;
[assembly: ExportRenderer(typeof(HelloRenderers.HelloView),
 typeof(HelloRenderers.Droid.HelloViewRenderer))]
namespace HelloRenderers.Droid
{
    public class HelloViewRenderer : ViewRenderer<HelloView, TextView>
    {
        protected override void OnElementChanged(ElementChangedEventArgs<HelloView> args)
        {
            base.OnElementChanged(args);
            if (Control == null)
            {
                SetNativeControl(new TextView(Context)
                {
                    Text = "Hello from Android!"
                });
                Control.SetTextSize(ComplexUnitType.Sp, 24);
            }
        }
    }
}

此HelloViewRenderer类派生自Android版本的ViewRenderer。 ViewRenderer的泛型参数表明Android TextView小部件支持HelloView类。
再次,在第一次调用OnElementChanged时,Control属性将为null。该方法必须创建本机Android TextView小部件并调用SetNativeControl。为了节省一点空间,新实例化的TextView对象直接传递给SetNativeControl方法。请注意,TextView构造函数需要Android Context对象。这是OnElementChanged的属性。
在调用SetNativeControl之后,ViewRenderer定义的Control属性是本机Android小部件,在本例中是TextView对象。该方法使用此Control属性在TextView对象上调用SetTextSize。在Android中,文本大小可以通过多种方式进行缩放。 ComplexUnitType.Sp枚举成员表示“缩放像素”,它与Xamarin.Forms处理Android中Label的字体大小的方式兼容。
这是HelloRenderers.UWP项目中的HelloViewRenderer的UWP版本:

using Xamarin.Forms.Platform.UWP;
using Windows.UI.Xaml.Controls;
[assembly: ExportRenderer (typeof(HelloRenderers.HelloView), 
 typeof(HelloRenderers.UWP.HelloViewRenderer))]
namespace HelloRenderers.UWP
{
    public class HelloViewRenderer : ViewRenderer<HelloView, TextBlock>
    {
        protected override void OnElementChanged(ElementChangedEventArgs<HelloView> args)
        {
            base.OnElementChanged(args);
            if (Control == null)
            {
                SetNativeControl(new TextBlock
                {
                    Text = "Hello from the UWP!",
                    FontSize = 24,
                });
            }
        }
    }
}

在所有Windows平台中,HelloView对象由Windows.UI.Xaml.Controls命名空间中的Windows运行时TextBlock呈现。
HelloRenderers.Windows和HelloRenderers.WinPhone项目中的HelloViewRenderer类大致相同,除了名称空间和用于设置TextBlock的Text属性的文本。
这是在三个标准平台上运行的程序:
2019_06_03_131710
注意如何通过使用HelloView对象上设置的常规HorizontalOptions和VerticalOptions属性来正确居中文本。 但是,您无法在HelloView上设置HorizontalTextAlignment和VerticalTextAlignment属性。 这些属性由Label定义,而不是由HelloView定义。
要将HelloView转换为用于显示文本的完整视图,您需要开始向HelloView类添加属性。 让我们来看看如何使用不同的示例将属性添加到渲染器。

目录
相关文章
|
6月前
|
存储
CocosCreator3.8研究笔记(二十二)CocosCreator 动画系统-动画剪辑和动画组件介绍
CocosCreator3.8研究笔记(二十二)CocosCreator 动画系统-动画剪辑和动画组件介绍
117 0
|
15天前
|
iOS开发 UED
实现一个自定义的iOS动画效果
【4月更文挑战第9天】本文将详细介绍如何在iOS平台上实现一个自定义的动画效果。我们将通过使用Core Animation框架来实现这个动画效果,并展示如何在不同的场景中使用它。文章的目标是帮助读者理解如何使用Core Animation框架来创建自定义动画,并提供一个简单的示例代码。
14 1
|
6月前
|
数据安全/隐私保护 iOS开发 MacOS
CocosCreator3.8研究笔记(二十四)CocosCreator 动画系统-动画编辑器实操-关键帧实现动态水印动画效果(2)
CocosCreator3.8研究笔记(二十四)CocosCreator 动画系统-动画编辑器实操-关键帧实现动态水印动画效果
|
6月前
|
数据安全/隐私保护
CocosCreator3.8研究笔记(二十四)CocosCreator 动画系统-动画编辑器实操-关键帧实现动态水印动画效果(1)
CocosCreator3.8研究笔记(二十四)CocosCreator 动画系统-动画编辑器实操-关键帧实现动态水印动画效果
|
6月前
CocosCreator3.8研究笔记(二十三)CocosCreator 动画系统-动画编辑器相关功能面板说明
CocosCreator3.8研究笔记(二十三)CocosCreator 动画系统-动画编辑器相关功能面板说明
|
9月前
|
JavaScript 定位技术
WebGis——Pixi开发vue项目之使用遮罩实现图形缓慢填充颜色(三)
WebGis——Pixi开发vue项目之使用遮罩实现图形缓慢填充颜色(三)
|
数据安全/隐私保护 iOS开发 开发者
iOS开发CoreGraphics核心图形框架之九——PDF文件的渲染与创建(一)
iOS开发CoreGraphics核心图形框架之九——PDF文件的渲染与创建
394 0
iOS开发CoreGraphics核心图形框架之九——PDF文件的渲染与创建(一)
第二十七章:自定义渲染器(六)
有趣的是,Android SeekBar小部件具有与Steps属性等效的功能,但不等同于Minimum和Maximum属性! 这怎么可能? SeekBar实际上定义了一个名为Max的整数属性,SeekBar的Progress属性始终是一个从0到Max的整数。
734 0
|
Windows
第二十七章:自定义渲染器(五)
渲染器和事件(1) 大多数Xamarin.Forms元素都是交互式的。他们通过触发事件来响应用户输入。如果在Xamarin.Forms自定义元素中实现事件,则可能还需要在呈现器中为本机控件触发的相应事件定义事件处理程序。
689 0
|
前端开发 Android开发 iOS开发
第二十七章:自定义渲染器(四)
渲染器和属性(2) 现在,对于iOS,EllipseUIView类是存在的,可以使用EllipseUIView作为本机控件来编写EllipseViewRenderer。 从结构上讲,这个类几乎与Windows渲染器相同: using System.
549 0

热门文章

最新文章