Xamarin.Forms 自定义控件(呈现器和效果)
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 控件。
效果没有它们附加到的容器、控件或元素的类型信息,因为它们可以附加到任何元素。 因此,当效果附加到它不支持的元素时,它应该适当地降级或引发异常。 但是,Container
、Control
和 Element
属性可以强制转换为其实现的类型。 若要详细了解这些类型,请参阅呈现器基类和本机控件。
每个特定于平台的 PlatformEffect
类都公开以下方法,必须替代这些方法以实现效果:
OnAttached
– 当效果附加到 Xamarin.Forms 控件时调用。 在每个特定于平台的效果类中,此方法的overridden是执行控件自定义逻辑的位置,以及在效果无法应用于指定的 Xamarin.Forms 控件的情况下的异常处理。OnDetached
– 当效果自 Xamarin.Forms 控件分离时调用。 在每个特定于平台的效果类中,此方法的overridden是执行任何效果清除的位置,例如取消注册事件处理程序。
此外,PlatformEffect
公开了 OnElementPropertyChanged
方法,该方法也可以被替代。 当该元素的属性发生更改时,调用此方法。 在每个特定于平台的效果类中,此方法的替代版本是响应 Xamarin.Forms 控件上的可绑定属性更改的位置。 应始终检查已更改的属性,因为可多次调用此替代。
效果创建
例如,创建效果以实现 在指向 Entry 控件时更改其背景颜色。
在每个特定于平台的项目中创建效果的过程如下:
- 创建
PlatformEffect
类的子类。 - 替代
OnAttached
方法并写入自定义控件的逻辑。 - 根据需要替代
OnDetached
方法并写入清理控件自定义的逻辑。 - 向效果类添加
ResolutionGroupName
属性。 此属性为效果设置一个公司范围的命名空间,以避免与同名的其他效果发生冲突。 请注意,每个项目只能应用一次该属性。 - 向效果类添加
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
控件创建自定义呈现器,可以利用呈现过程来实现特定于平台的自定义。 执行此操作的过程如下:
- 创建 Xamarin.Forms 自定义控件。
- 使用 Xamarin.Forms 中的自定义控件。
- 在每个平台上为控件创建自定义呈现器。
注:本文介绍如何创建简单的自定义呈现器。 但是,要在每个平台上实现具有不同背景色的 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>
在每个平台上创建自定义呈现器
创建自定义呈现器类的过程如下所示:
- 创建呈现本机控件的
EntryRenderer
类的子类。 - 替代呈现本机控件的
OnElementChanged
方法并写入逻辑以自定义控件,创建相应的 Xamarin.Forms 控件时将调用此方法【相当于构造函数】。 - 向自定义呈现器类添加
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
创建自定义呈现器,可以利用呈现过程来实现特定于平台的自定义。 执行此操作的过程如下:
- 创建 Xamarin.Forms 自定义控件。
- 使用 Xamarin.Forms 中的自定义控件。
- 在每个平台上为控件创建自定义呈现器。
现在将依次讨论每个项目,以实现 NativeListView
呈现器,该呈现器利用特定于平台的列表控件和本机单元布局。 移植包含可以重复使用的列表和单元代码的现有本机应用时,此方案很有用。 此外,它还允许对可能影响性能的列表控件功能进行详细自定义,例如数据虚拟化。
自定义WebView
Xamarin.Forms WebView
是在应用中显示 Web 和 HTML 内容的视图。 可以创建扩展 WebView
以允许从 JavaScript 调用 C# 代码的自定义呈现器。
WebView
可从 C# 调用 JavaScript 函数,并将任何结果返回给调用的 C# 代码。 有关详细信息,请参阅调用 JavaScript。
通过在每个平台上为 WebView
创建自定义呈现器,可使用呈现过程来实现平台自定义。 执行此操作的过程如下:
- 创建
HybridWebView
自定义控件。 - 使用 Xamarin.Forms 中的
HybridWebView
。 - 在每个平台上为
HybridWebView
创建自定义呈现器。
现在,依次讨论每个项目以实现 HybridWebView
呈现器,该呈现器可增强 Xamarin.Forms WebView
以允许从 JavaScript 调用 C# 代码。 HybridWebView
实例将用于显示要求用户输入其名称的 HTML 页。 然后,当用户单击 HTML 按钮,JavaScript 函数将调用 C# Action
显示一个包含用户名称的弹出项。
Xamarin.Forms 自定义控件(呈现器和效果)的更多相关文章
- 自定义xamarin.forms Entry 背景色以及边框
创建 一个Xamarin.Forms自定义控件. 自定义Entry控件可以通过继承来创建Entry控制,显示在下面的代码示例: public class MyEntry : Entry { ...
- C#使用Xamarin开发可移植移动应用(2.Xamarin.Forms布局,本篇很长,注意)附源码
前言 系列目录 C#使用Xamarin开发可移植移动应用目录 源码地址:https://github.com/l2999019/DemoApp 可以Star一下,随意 - - 一点感想 很意外的,第一 ...
- Xamarin.Forms快速入门-深入探讨
官网链接 项目介绍 以Notes项目为例,The Notes application consists of one solution containing four projects, as sho ...
- Xamarin.Forms一些常见问题
安装 1.查看Xaramin.Forms的版本 在vs项目中查看引用的包(Xamarin.Forms)的版本,或者直接进文件夹看 C:\Microsoft\Xamarin\NuGet\xamarin. ...
- Xamarin.Forms之XAML
官网参考 XAML基础知识 XAML(eXtensible Application Markup Language)可扩展应用程序标记语言,允许开发者在Xamarin.Forms应用中采用标记而不是代 ...
- Xamarin.Forms介绍
On May 28, 2014, Xamarin introduced Xamarin.Forms, which allows you to write user-interface code tha ...
- Xamarin Forms:小马过河,王者归来
因为我媳妇的原因,去年下半年从零开始学习Android原生开发,做了一个答题库app.整体给我的感觉是入门难度不大,前期折腾一番,大部分时间都是花在开发上面,其实任何一门语言都是如此. 今年我又有另一 ...
- Xamarin.Forms之页面及导航
参考链接: Xamarin. Forms 页面 Xamarin.Forms 导航 Xamarin.Forms 第04局:页面 Xamarin.Forms页面代表跨平台的移动应用程序屏幕. 下文描述的所 ...
- Xamarin.Forms 入门
介绍 Xamarin.Forms是一个开源UI框架,Xamarin.Forms允许开发人员从单个共享代码库构建Android,iOS和Windows应用程序. Xamarin.Forms允许开发人员使 ...
随机推荐
- .NET下使用HTTP请求的正确姿势
来源:Lewis.Zou cnblogs.com/modestmt/p/7724821.html 一.前言 去年9月份的时候我看到过外国朋友关于.NET Framework下HttpClient缺陷的 ...
- Python将背景图片的颜色去掉
一.问题 在使用图片的时候有时候我们希望把背景变成透明的,这样就只关注于图片本身.比如在连连看中就只有图片,而没有背景,其实我个人感觉有背景好看一点. 二.解决 我们需要使用RGBA(Red,Gr ...
- [Atcoder AGC029C]Lexicographic constraints
题目大意:给定$n$个字符串的长度$a_i$,问至少用几种字符可以构造出字符串$s_1\sim s_n$,满足$|s_i|=a_i$且$s_1<s_2<\cdots<s_n$. $ ...
- Java学习:等待唤醒机制
等待唤醒机制 线程的状态 NEW 至今尚未启动的线程处于这种状态 RUNNABLE 正在Java虚拟机中执行的线程处于这种状态 BLOCKED 受阻塞并等待某个监视器锁的线程处于这种状态 WA ...
- Replication:事务复制 Subscriber的主键列是只读的
在使用Transactional Replication时,Subscriber 被认为是“Read-Only”的 , All data at the Subscriber is “read-only ...
- LATEX 数学公式基本语法
作者:@houkai本文为作者原创,转载请注明出处:https://www.cnblogs.com/houkai/p/3399646.html TEX 是Donald E. Knuth 编写的一个以排 ...
- MySQL里默认的几个库是干啥的?
本文涉及:MySQL安装后自带的4个数据库:information_schema. performance_schema.sys.mysql的作用及其中各个表所存储的数据含义 information_ ...
- js中 json对象与json字符串相互转换的几种方式
以下总结js中 json对象与json字符串相互转换的几种方式: 一.JSON对象转化为JSON字符串 1.使用JSON.stringify()方法进行转换 该方法不支持较老版本的IE浏览器,比如:i ...
- MES系统帮助冷轧厂实现次品的流程解析
为了解决现场实际生产过程中纸质不良品卡片易丢失.周期长.传递缓慢,不能起到质量警示和生产预警等诸多方面的问题,某冷轧厂采取了在MES系统中实现不良品业务流程的方案,完全替代和取消了纸质不良品卡片,在M ...
- Solr新特性【4.x,5.x,6.x,7.x】
一.Solr4.x新特性 1.近实时搜索 Solr的近实时搜索[Near Real-Time,NRT]功能实现了文档添加到搜索的快速进行,以应对搜索快速变化的数据. 2.原子更新与乐观并发 原子更新功 ...