Xamarin.Forms 使用目标平台的本机控件呈现用户界面,从而让 Xamarin.Forms 应用程序为每个平台保留了相应的界面外观。凭借效果,无需进行自定义呈现器实现,即可自定义每个平台上的本机控件,通常用于细微的样式更改。

Xamarin.Forms 页、布局和控件提供常见的 API,用于描述跨平台的移动用户界面。 通过 Renderer 类可以在每个平台上以不同方式呈现每个页面、布局和控件,反过来又可以创建本机控件(对应于 Xamarin.Forms 表示),在屏幕上排列该控件,并添加共享代码中指定的行为。

开发人员可以实现自定义 Renderer 类,以自定义控件的外观和/或行为。 可以将给定类型的自定义呈现器添加到一个应用程序项目中,以便在同一个位置自定义控件,同时允许其他平台上的默认行为,或者将不同的自定义呈现器添加到每个应用程序项目中,以便在 iOS、Android 和通用 Windows 平台 (UWP) 上创建不同的外观和感觉。 但是,实现自定义渲染器类以执行简单的控件自定义通常是一项重量级的响应。 效果简化了此过程,通常用于较小的样式更改。有关详细信息,请参阅效果

效果

通过将PlatformEffect控件子类化,可以在特定于平台的项目中创建效果,然后通过将效果附加到Xamarin.Forms .NET Standard库或共享库项目中的适当控件来使用效果。

为什么要在自定义呈现器上使用效果?

效果简化了控件的自定义、可重用并且可以通过参数化进一步增加重用。

任何可以使用效果达成的事情也可以使用自定义呈现器达成。 但是,自定义呈现器提供比效果更多的灵活性和自定义。 以下指南列出了在自定义呈现器上选择效果的情况:

  • 当更改特定于平台的控件的属性能达成所需结果时,建议使用效果。
  • 当需要替代特定于平台的控件的方法时,需要使用自定义呈现器。
  • 当需要替换实现 Xamarin.Forms 控件的特定于平台的控件时,需要使用自定义呈现器。

子类化 PlatformEffect 类

每个特定于平台的 PlatformEffect 类都公开以下属性:

  • Container – 引用用于实现布局的特定于平台的控件。
  • Control – 引用用于实现 Xamarin.Forms 控件的特定于平台的控件。
  • Element – 引用正在呈现的 Xamarin.Forms 控件。

效果没有它们附加到的容器、控件或元素的类型信息,因为它们可以附加到任何元素。 因此,当效果附加到它不支持的元素时,它应该适当地降级或引发异常。 但是,ContainerControl 和 Element 属性可以强制转换为其实现的类型。 若要详细了解这些类型,请参阅呈现器基类和本机控件

每个特定于平台的 PlatformEffect 类都公开以下方法,必须替代这些方法以实现效果:

  • OnAttached – 当效果附加到 Xamarin.Forms 控件时调用。 在每个特定于平台的效果类中,此方法的overridden是执行控件自定义逻辑的位置,以及在效果无法应用于指定的 Xamarin.Forms 控件的情况下的异常处理。
  • OnDetached – 当效果自 Xamarin.Forms 控件分离时调用。 在每个特定于平台的效果类中,此方法的overridden是执行任何效果清除的位置,例如取消注册事件处理程序。

此外,PlatformEffect 公开了 OnElementPropertyChanged 方法,该方法也可以被替代。 当该元素的属性发生更改时,调用此方法。 在每个特定于平台的效果类中,此方法的替代版本是响应 Xamarin.Forms 控件上的可绑定属性更改的位置。 应始终检查已更改的属性,因为可多次调用此替代。

效果创建

例如,创建效果以实现 在指向 Entry 控件时更改其背景颜色。

在每个特定于平台的项目中创建效果的过程如下:

  1. 创建 PlatformEffect 类的子类。
  2. 替代 OnAttached 方法并写入自定义控件的逻辑。
  3. 根据需要替代 OnDetached 方法并写入清理控件自定义的逻辑。
  4. 向效果类添加 ResolutionGroupName 属性。 此属性为效果设置一个公司范围的命名空间,以避免与同名的其他效果发生冲突。 请注意,每个项目只能应用一次该属性。
  5. 向效果类添加 ExportEffect 属性。 该属性使用 Xamarin.Forms 所用的唯一 ID 以及组名注册效果,以便在将应用于控件之前定位该效果。 该属性接受两个参数 - 效果的类型名称和一个唯一的字符串,该字符串用于在将效果应用于控件之前定位该效果。

然后,可以通过将效果附加到相应控件来使用该效果。

1、在各平台上创建效果

[assembly: ResolutionGroupName("MyCompany")]
[assembly: ExportEffect(typeof(EffectsDemo.Droid.FocusEffect), nameof(EffectsDemo.Droid.FocusEffect))]
namespace EffectsDemo.Droid
{
public class FocusEffect : PlatformEffect
{
protected override void OnAttached() {

在OnAttached()中设置控件【需要设置效果的控件】的一些外观。

属性ResolutionGroupName和ExportEffect的第二个参数,用于定位效果,"MyCompany.FocusEffect"【在使用效果时 需要】

2、使用效果(在XAML中)

RoutingEffect 类它表示一个独立于平台的效果,该效果包装通常特定于平台的内部效果。

在运行时初始化 Entry 时,向控件的 Effects 集合添加了 MyCompany.FocusEffect 的新实例。

传递参数

效果参数可以通过属性定义,从而可以重用效果。 然后,可以在实例化效果时通过为每个属性指定值来将参数传递给效果。

1、将效果参数作为公共语言运行时(CLR)属性传递
公共语言运行时(CLR)属性可用于定义不响应运行时属性更改的效果参数。 本文演示了如何使用CLR属性将参数传递给效果。

2、将效果参数作为附加属性传递
附加属性可用于定义响应运行时属性更改的效果参数。 本文演示了如何使用附加属性将参数传递给效果,以及在运行时更改参数。

作为CLR属性的参数

创建效果参数

public class ShadowEffect : RoutingEffect
{
public float Radius { get; set; } public Color Color { get; set; } public float DistanceX { get; set; } public float DistanceY { get; set; } public ShadowEffect () : base ("MyCompany.LabelShadowEffect")
{
}
}

使用效果

<Label Text="Label Shadow Effect" ...>
<Label.Effects>
<local:ShadowEffect Radius="5" DistanceX="5" DistanceY="5">
<local:ShadowEffect.Color>
<OnPlatform x:TypeArguments="Color">
<On Platform="iOS" Value="Black" />
<On Platform="Android" Value="White" />
<On Platform="UWP" Value="Red" />
</OnPlatform>
</local:ShadowEffect.Color>
</local:ShadowEffect>
</Label.Effects>
</Label>

在各个平台上创建效果:略

作为附加属性的参数

创建效果参数

public static class ShadowEffect
{
public static readonly BindableProperty HasShadowProperty =
BindableProperty.CreateAttached ("HasShadow", typeof(bool), typeof(ShadowEffect), false, propertyChanged: OnHasShadowChanged);
public static readonly BindableProperty ColorProperty =
BindableProperty.CreateAttached ("Color", typeof(Color), typeof(ShadowEffect), Color.Default);
public static readonly BindableProperty RadiusProperty =
BindableProperty.CreateAttached ("Radius", typeof(double), typeof(ShadowEffect), 1.0);
public static readonly BindableProperty DistanceXProperty =
BindableProperty.CreateAttached ("DistanceX", typeof(double), typeof(ShadowEffect), 0.0);
public static readonly BindableProperty DistanceYProperty =
BindableProperty.CreateAttached ("DistanceY", typeof(double), typeof(ShadowEffect), 0.0); public static bool GetHasShadow (BindableObject view)
{
return (bool)view.GetValue (HasShadowProperty);
} public static void SetHasShadow (BindableObject view, bool value)
{
view.SetValue (HasShadowProperty, value);
}
... static void OnHasShadowChanged (BindableObject bindable, object oldValue, object newValue)
{
var view = bindable as View;
if (view == null) {
return;
} bool hasShadow = (bool)newValue;
if (hasShadow) {
view.Effects.Add (new LabelShadowEffect ());
} else {
var toRemove = view.Effects.FirstOrDefault (e => e is LabelShadowEffect);
if (toRemove != null) {
view.Effects.Remove (toRemove);
}
}
} class LabelShadowEffect : RoutingEffect
{
public LabelShadowEffect () : base ("MyCompany.LabelShadowEffect")
{
}
}
}

ShadowEffect 包含五个附加属性,以及每个附加属性的 static getter 和 setter。 其中四个属性表示要传递给每个特定于平台的 LabelShadowEffect 的参数。 ShadowEffect 类还定义了 HasShadow 附加属性,用于控制 ShadowEffect 类附加到的控件的效果的添加或删除。 该附加属性注册属性值更改时执行的 OnHasShadowChanged 方法。 此方法根据 HasShadow 附加属性的值添加或删除效果。

嵌套 LabelShadowEffect 类是 RoutingEffect 类的子类,支持添加和删除效果。

其他详细的看示例。

自定义呈现器Renderer

Xamarin.Forms 使用目标平台的本机控件呈现用户界面,从而让 Xamarin.Forms 应用程序为每个平台保留了相应的界面外观。自定义呈现器允许开发人员重写此过程,自定义每个平台上 Xamarin.Forms 控件的外观和行为。

官网参考

Renderer Base Classes and Native Controls

每个Xamarin.Forms控件都有一个用于每个平台的随附渲染器,这些渲染器创建本机控件的实例。 本文列出了实现每个Xamarin.Forms页面,布局,视图和单元格的渲染器和本机控件类。

除MapRenderer类外,特定于平台的渲染器可在以下命名空间中找到:

  • iOS – Xamarin.Forms.Platform.iOS
  • Android – Xamarin.Forms.Platform.Android
  • Android(AppCompat)– Xamarin.Forms.Platform.Android.AppCompat
  • 通用Windows平台(UWP)– Xamarin.Forms.Platform.UWP

可以在以下命名空间中找到MapRenderer类:

  • iOS – Xamarin.Forms.Maps.iOS
  • Android – Xamarin.Forms.Maps.Android
  • 通用Windows平台(UWP)– Xamarin.Forms.Maps.UWP

有关 Xamarin.Forms 控件映射到的呈现器和本机控件类的详细信息,请参阅呈现器基类和本机控件

自定义Entry

Xamarin.Forms Entry 控件允许对单行文本进行编辑。本文演示了如何为 Entry 控件创建自定义呈现器,使开发人员能够使用自己特定于平台的自定义呈现替代默认本机呈现。

每个 Xamarin.Forms 控件都有一个附带的呈现器,适用于创建本机控件实例的各个平台。

Xamarin.Forms 应用程序呈现 Entry 控件时,在 iOS 中实例化 EntryRenderer 类,进而实例化本机 UITextField 控件。 在 Android 平台上,EntryRenderer 类实例化 EditText 控件。 在通用 Windows 平台 (UWP) 上,EntryRenderer 类实例化 TextBox 控件。

下图说明了 Entry 控件和实现它的相应本机控件之间的关系:

通过在每个平台上为 Entry 控件创建自定义呈现器,可以利用呈现过程来实现特定于平台的自定义。 执行此操作的过程如下:

  1. 创建 Xamarin.Forms 自定义控件。
  2. 使用 Xamarin.Forms 中的自定义控件。
  3. 在每个平台上为控件创建自定义呈现器。

注:本文介绍如何创建简单的自定义呈现器。 但是,要在每个平台上实现具有不同背景色的 Entry,无需创建自定义呈现器。 这可以通过使用 Device 类或 OnPlatform 标记扩展来轻松实现,以提供特定于平台的值。 有关详细信息,请参阅提供特定于平台的值和 OnPlatform 标记扩展

创建和使用自定义Entry控件

定义类(不必是控件,不需要xaml)MyEntry,

public class MyEntry : Entry { }
<ContentPage ...
xmlns:local="clr-namespace:CustomRenderer;assembly=CustomRenderer"
...>
...
<local:MyEntry Text="In Shared Code" />
...
</ContentPage>

在每个平台上创建自定义呈现器

创建自定义呈现器类的过程如下所示:

  1. 创建呈现本机控件的 EntryRenderer 类的子类。
  2. 替代呈现本机控件的 OnElementChanged 方法并写入逻辑以自定义控件,创建相应的 Xamarin.Forms 控件时将调用此方法【相当于构造函数】。
  3. 向自定义呈现器类添加 ExportRenderer 属性,以指定其将用于呈现 Xamarin.Forms 控件,此属性用于向 Xamarin.Forms 注册自定义呈现器。

Android为例,

using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(MyEntry), typeof(MyEntryRenderer))]
namespace CustomRenderer.Android
{
class MyEntryRenderer : EntryRenderer
{
public MyEntryRenderer(Context context) : base(context)
{
} protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e); if (Control != null)
{
Control.SetBackgroundColor(global::Android.Graphics.Color.LightGreen);
}
}
}
}

对基类的OnElementChanged方法的调用将实例化一个Android EditText控件,并将对该控件的引用分配给渲染器的Control属性。 然后使用Control.SetBackgroundColor方法将背景色设置为浅绿色。

自定义ContentPage

实现自定义的View

Xamarin.Forms自定义用户界面控件应从View类派生,该类用于在屏幕上放置布局和控件。

每个Xamarin.Forms视图都有一个用于每个平台的随附渲染器,这些渲染器创建本机控件的实例。

  • 当iOS中的Xamarin.Forms应用程序呈现View时,将实例化ViewRenderer类,从而实例化本机UIView控件。
  • 在Android平台上,ViewRenderer类实例化本机View控件。
  • 在通用Windows平台(UWP)上,ViewRenderer类实例化本机FrameworkElement控件。

自定义ListView

通过在每个平台上为 ListView 创建自定义呈现器,可以利用呈现过程来实现特定于平台的自定义。 执行此操作的过程如下:

  1. 创建 Xamarin.Forms 自定义控件。
  2. 使用 Xamarin.Forms 中的自定义控件。
  3. 在每个平台上为控件创建自定义呈现器。

现在将依次讨论每个项目,以实现 NativeListView 呈现器,该呈现器利用特定于平台的列表控件和本机单元布局。 移植包含可以重复使用的列表和单元代码的现有本机应用时,此方案很有用。 此外,它还允许对可能影响性能的列表控件功能进行详细自定义,例如数据虚拟化。

自定义WebView

Xamarin.Forms WebView 是在应用中显示 Web 和 HTML 内容的视图。 可以创建扩展 WebView 以允许从 JavaScript 调用 C# 代码的自定义呈现器。

WebView 可从 C# 调用 JavaScript 函数,并将任何结果返回给调用的 C# 代码。 有关详细信息,请参阅调用 JavaScript

通过在每个平台上为 WebView 创建自定义呈现器,可使用呈现过程来实现平台自定义。 执行此操作的过程如下:

  1. 创建HybridWebView自定义控件。
  2. 使用 Xamarin.Forms 中的 HybridWebView
  3. 在每个平台上为 HybridWebView创建自定义呈现器。

现在,依次讨论每个项目以实现 HybridWebView 呈现器,该呈现器可增强 Xamarin.Forms WebView 以允许从 JavaScript 调用 C# 代码。 HybridWebView 实例将用于显示要求用户输入其名称的 HTML 页。 然后,当用户单击 HTML 按钮,JavaScript 函数将调用 C# Action 显示一个包含用户名称的弹出项。

示例地址

Xamarin.Forms 自定义控件(呈现器和效果)的更多相关文章

  1. 自定义xamarin.forms Entry 背景色以及边框

    创建   一个Xamarin.Forms自定义控件.     自定义Entry控件可以通过继承来创建Entry控制,显示在下面的代码示例: public class MyEntry : Entry { ...

  2. C#使用Xamarin开发可移植移动应用(2.Xamarin.Forms布局,本篇很长,注意)附源码

    前言 系列目录 C#使用Xamarin开发可移植移动应用目录 源码地址:https://github.com/l2999019/DemoApp 可以Star一下,随意 - - 一点感想 很意外的,第一 ...

  3. Xamarin.Forms快速入门-深入探讨

    官网链接 项目介绍 以Notes项目为例,The Notes application consists of one solution containing four projects, as sho ...

  4. Xamarin.Forms一些常见问题

    安装 1.查看Xaramin.Forms的版本 在vs项目中查看引用的包(Xamarin.Forms)的版本,或者直接进文件夹看 C:\Microsoft\Xamarin\NuGet\xamarin. ...

  5. Xamarin.Forms之XAML

    官网参考 XAML基础知识 XAML(eXtensible Application Markup Language)可扩展应用程序标记语言,允许开发者在Xamarin.Forms应用中采用标记而不是代 ...

  6. Xamarin.Forms介绍

    On May 28, 2014, Xamarin introduced Xamarin.Forms, which allows you to write user-interface code tha ...

  7. Xamarin Forms:小马过河,王者归来

    因为我媳妇的原因,去年下半年从零开始学习Android原生开发,做了一个答题库app.整体给我的感觉是入门难度不大,前期折腾一番,大部分时间都是花在开发上面,其实任何一门语言都是如此. 今年我又有另一 ...

  8. Xamarin.Forms之页面及导航

    参考链接: Xamarin. Forms 页面 Xamarin.Forms 导航 Xamarin.Forms 第04局:页面 Xamarin.Forms页面代表跨平台的移动应用程序屏幕. 下文描述的所 ...

  9. Xamarin.Forms 入门

    介绍 Xamarin.Forms是一个开源UI框架,Xamarin.Forms允许开发人员从单个共享代码库构建Android,iOS和Windows应用程序. Xamarin.Forms允许开发人员使 ...

随机推荐

  1. python selenium IE Firxfor pyinstaller

    以前在python环境下selenium 主要用的是chromdriver,这次发现老是报错(Timeout), 实际又是正确的, 可能是和chrome版本不正确,再加上我程序蹦来就在windows环 ...

  2. centos lnmp一键安装

    安装 系统需求: 需要2 GB硬盘剩余空间 128M以上内存,OpenVZ的建议192MB以上(小内存请勿使用64位系统) Linux下区分大小写,输入命令时请注意! 安装步骤: 1.使用putty或 ...

  3. asp.net图片浏览器效果

    技术来源于同学会实践 前台设计 <%@ Page Language="C#" AutoEventWireup="true" CodeFile=" ...

  4. Javascript文件上传插件

    jQuery File Uploader 这是最受欢迎的 jQuery 文件上传组件,支持批量上传,拖放上传,显示上传进度条以及校验功能. 支持预览图片.音频和视频,支持跨域上传和客户端图片缩放,支持 ...

  5. jsGrid使用入门

    jsGrid使用入门 原创蓝天上的一朵云 本文链接:https://blog.csdn.net/u012846041/article/details/82735811 jsGrid资源地址: http ...

  6. scarpy设置日志打印级别和存储位置

    在settings.py中配置 日志级别设置 LOG_LEVEL = 'ERROR' # 当LOG_LEVEL设置为ERROR时,在进行日志打印时,只是打印ERROR级别的日志 日志存储设置 LOG_ ...

  7. Django---Django的ORM的一对多操作(外键操作),ORM的多对多操作(关系管理对象),ORM的分组聚合,ORM的F字段查询和Q字段条件查询,Django的事务操作,额外(Django的终端打印SQL语句,脚本调试)

    Django---Django的ORM的一对多操作(外键操作),ORM的多对多操作(关系管理对象),ORM的分组聚合,ORM的F字段查询和Q字段条件查询,Django的事务操作,额外(Django的终 ...

  8. JS基础 —— 跨域

    为什么会跨域 浏览器的同源策略(MDN:https://developer.mozilla.org/zh-CN/docs/Web/Security/Same-origin_policy) URL:协议 ...

  9. Web前端面试总结(别人的)

    http://note.youdao.com/noteshare?id=0bfbe45de0de0bc4735f867e5a6c528f&sub=D52F5C079DDE49F99A5118D ...

  10. android studio学习----构建编译

    项目创建成功后会自动下载Gradle,这个过程特别慢,建议翻墙.下载的Gradle在Windows平台会默认在 C:\Documents and Settings\<用户名>.gradle ...