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. MyBatis系列(二) MyBatis接口绑定与多参数传递

    前言 通过上一篇博文的,已经可以做到通过MyBatis连接数据库,现在再来介绍一种方法通过接口绑定SQL语句. 不使用接口绑定的方式 不使用接口绑定的方式,是通过调用SqlSession中的selec ...

  2. Kafka学习笔记之Kafka日志删出策略

    0x00 概述 kafka将topic分成不同的partitions,每个partition的日志分成不同的segments,最后以segment为单位将陈旧的日志从文件系统删除. 假设kafka的在 ...

  3. Grafana官方和社区提供的dashboard

    详见:https://grafana.com/grafana/dashboards 可以在左侧配置筛选条件,非常强大. 当然Grafana中所有的Dashboard通过JSON进行共享,下载并且导入这 ...

  4. vue.js 如何加载本地json文件

    在项目开发的过程中,因为无法和后台的数据做交互,所以我们可以自建一个假数据文件(如data.json)到项目文件夹中,这样我们就可以模仿后台的数据进行开发.但是,如何在一个vue.js 项目中引入本地 ...

  5. Middle English finaunce金融

    Etymology finance From Middle English finaunce, a surety bond.A supply of money or goods. With thy b ...

  6. byte[],File和InputStream的相互转换

    File.FileInputStream 转换为byte[] File file = new File("test.txt"); InputStream input = new F ...

  7. 12306 抢票项目霸榜 GitHub,标星即将破万

    十一将至,你买到回家的火车票了吗?如果没有,你可以试着打开 GitHub,在搜索栏键入 12306 的关键词,我相信你会发现一个新大陆.没错,这里有 1572 个抢票项目.它们大多用 Python.J ...

  8. Django 之 ContentType组件

    一.什么是 ContentTypes ContentTypes 是 Django 内置的一个应用,它可以追踪记录项目中所有 app 和 model 的对应关系,并记录在 django_content_ ...

  9. Kali下安装Java环境

    <-----教你在Kali下安装Java环境-----> 1. 下载1.8u121的JAVA JDK 下载地址:http://java.sun.com/javase/downloads/i ...

  10. JavaWeb项目前后端分离

    前戏   前后端分离已成为互联网项目开发的业界标准使用方式,通过nginx+tomcat的方式(也可以中间加一个nodejs)有效的进行解耦, 并且前后端分离会为以后的大型分布式架构.弹性计算架构.微 ...