今天就跟大家聊聊有关如何借助Xamarin.Forms跨移动平台共享UI代码,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。
借助 Xamarin,您可以使用 C# 构建美观的本机移动应用和在平台之间共享您的大部分代码。传统上,您必须对每个目标平台设计单独的 UI。但是,借助 Xamarin.Forms,您可以构建一个在所有平台中本机呈现的 UI。
Xamarin.Forms 是跨平台 UI 抽象层。可以使用它在平台间共享 UI 和后端代码,而同时仍提供完全本机 UI 体验。因为它们是本机的,所以您的控件和小组件将具有每个目标平台的外观。
Xamarin.Forms 与 Model-View-ViewModel (MVVM) 设计模式完全兼容,因此可以在视图模型类中将页面元素绑定到属性和命令。
如果您愿意以声明方式设计您的页面,则可以使用标记语言 XAML,XAML 具有资源字典、动态资源、数据绑定、命令、触发器和行为等功能。
Xamarin.Forms 有一个小巧、易于使用的 API。如果您需要更深入地访问平台的本机 UI,可以创建自定义视图和特定于平台的呈现器。这尽管听起来很复杂,但它实际上只是一种可访问本机 UI 的方法,并且 Xamarin 网站有充足示例来帮助您完成该任务。
您可以使用 Xamarin.Forms 附带的任何现成页面、布局和视图开始操作。在您的应用逐渐完善并且您发现新用例和设计机会时,您可能马上就需依赖 Xamarin.Forms 支持 XAML、MVVM、特定于自定义平台的呈现器和各种其他功能(如动画和数据模板)。
我将使用特定示例概述 Xamarin 功能,演示如何在不同的目标平台之间共享大部分 UI 代码,以及如何在必要时合并特定于平台的代码。
首先,打开 Visual Studio 或 Xamarin Studio 中的 NuGet 包管理器,并检查 Xamarin.Forms 是否为新版本。因为仅仅在任一 IDE 中打开 Xamarin.Forms 解决方案,不会告知您新版本,所以检查更新的 NuGet 包是否为确保获得最新增强功能的唯一方法。
创建 Xamarin.Forms 解决方案确保您已获得最新版本 Xamarin.Forms 后,创建一个空白应用 (Xamarin.Forms Portable) 解决方案。
您的解决方案具有三个特定于平台的项目和一个可移植类库 (PCL)。在 PCL 中创建您的页面。首先创建一个基本的登录页面。
使用 C# 创建页面向 PCL 项目中添加一个类。然后添加控件(在 Xamarin 中称为“视图”),如图 1 中所示。
图 1 添加视图(控件)
public class LogInPage : ContentPage
{
public LogInPage()
{
Entry userEntry = new Entry { Placeholder = "Username" };
Entry passEntry =
new Entry { Placeholder = "Password", IsPassword = true };
Button submit = new Button { };
Content = new StackLayout
{
Padding = 20,
VerticalOptions = LayoutOptions.Center,
Children = { userEntry, passEntry, submit }
};
}
}
若要在应用启动时显示页面,打开 MyApp 类并将其中一个实例分配给 MainPage 属性:
public class MyApp : Application
{
public MyApp()
{
MainPage = new LogInPage();
}
}
这是讨论应用程序类的好时机。从 v1.3.0 开始,所有 Xamarin.Forms 应用将都包含此类。它是 Xamarin.Forms 应用的入口点,除此之外,它还提供了生命周期事件以及所有可序列化数据的永久数据存储区(属性字典)。如果需要从应用任意位置访问此类的实例,您可以使用静态 Application.Current 属性。
在前面的示例中,我已删除应用程序类内部的默认代码,并用一行代码代替,从而使 LogInPage 显示您何时运行应用。它显示应用何时运行,因为此代码将页面 (LogInPage) 分配给了应用程序类的 MainPage 属性。您必须在应用程序类的构造函数中对其进行设置。
您还可以重写此类中的三个方法:
OnStart 方法,第一次启动应用时调用。
OnSleep 方法,当应用要进入后台状态时调用。
OnResume 方法,当从后台状态返回应用时调用。
一般情况下,页面不是非常有趣,直到您将他们与某种形式的数据或行为连接,因此我将介绍如何执行该操作。
将页面绑定到数据如果您使用 MVVM 设计模式,则可以创建一个(如图 2 中所示)实现 INotifyPropertyChanged 接口的类。
图 2 实现 INotifyPropertyChanged 接口
public class LoginViewModel : INotifyPropertyChanged
{
private string usrnmTxt;
private string passWrd;
public string UsernameText
{
get { return usrnmTxt; }
set
{
if (usrnmTxt == value)
return;
usrnmTxt = value;
OnPropertyChanged("UsernameText");
}
}
public string PassWordText
{
get { return passWrd; }
set
{
if (passWrd == value)
return;
passWrd = value;
OnPropertyChanged("PassWrd");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
您可以将登录页面的视图绑定到该类的属性(如图 3 中所示)。
图 3 将视图绑定到类属性
public LogInPage()
{
Entry userEntry = new Entry { Placeholder = "Username" };
userEntry.SetBinding(Entry.TextProperty, "UsernameText");
Entry passEntry =
new Entry { Placeholder = "Password", IsPassword = true };
passEntry.SetBinding(Entry.TextProperty, "PasswordText");
Button submit = new Button { Text = "Submit" };
Content = new StackLayout
{
Padding = 20,
VerticalOptions = LayoutOptions.Center,
Children = { userEntry, passEntry, submit }
};
BindingContext = new LoginViewModel();
}
若要阅读有关如何绑定到 Xamarin.Forms 应用中数据的详细信息,请参阅 Xamarin 站点 bit.ly/1uMoIUX 上的“从数据绑定到 MVVM”。
使用 XAML 创建页面对于较小的应用,使用 C# 创建 UI 是完全合理的方法。但是,随着应用大小的增长,您可能会发现自己键入了大量的重复代码。您可以通过使用 XAML 避免该问题,,而不是通过 C# 代码。
将窗体 XAML 页面项添加到您的 PCL 项目。然后将标记添加到页面,如图 4 中所示。
图 4 将标记添加到窗体 XAML 页面
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Jason3.LogInPage"
xmlns:local="clr-namespace:XamarinForms;assembly=XamarinForms">
<StackLayout VerticalOptions="Center">
<StackLayout.BindingContext>
<local:LoginViewModel />
</StackLayout.BindingContext>
<Entry Text="{Binding UsernameText}" Placeholder="Username" />
<Entry Text="{Binding PasswordText}"
Placeholder="Password" IsPassword="true" />
<Button Text="Login" Command="{Binding LoginCommand}" />
</StackLayout>
</ContentPage>
如果您编写过 Windows Presentation Foundation (WPF) 应用,那么会对图 4 中的 XAML 感到很熟悉。但是,这些标记是不同的,因为它们指的是 Xamarin.Forms 类型。此外,根元素引用 Xamarin.Forms.Element 类的子类。Xamarin.Forms 应用中的所有 XAML 文件必须都这样做。
若要了解有关使用 XAML 在 Xamarin.Forms 应用中创建页面的详细信息,请参阅 Xamarin 网站 bit.ly/1xAKvRN 上的“适用于 Xamarin.Forms 的 XAML”。
与其他本机移动平台相比,Xamarin.Forms 具有相对较少的 API。这样您可以更轻松地设计页面,但有时 Xamarin.Forms 不按您想要的方式在一个或多个平台目标上呈现视图。
如果遇到此障碍,只需创建自定义视图,这只是一个可用于 Xamarin.Forms 的任何视图的子类。
若要使视图显示在页面上,请扩展视图呈现器。在更高级的情况下,您甚至可以从头创建自定义呈现器。自定义呈现器代码是特定于平台的,因此您不能共享此代码。但这种方法值这个价格,因为它可以引入本机功能和应用可用性。
创建自定义视图首先,创建 Xamarin.Forms 中提供的任一视图的子类。下面是两个自定义视图的代码:
public class MyEntry : Entry {}
public class RoundedBoxView : BoxView {}
扩展现有的呈现器图 5 扩展可以呈现 iOS 平台的条目视图的呈现器。您应将此类放在 iOS 平台项目中。此呈现器设置底层本机文本字段的颜色和样式。
图 5 扩展现有的呈现器
[assembly: ExportRenderer (typeof (MyEntry), typeof (MyEntryRenderer))]
namespace CustomRenderer.iOS
{
public class MyEntryRenderer : EntryRenderer
{
protected override void OnElementChanged
(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged (e);
if (e.OldElement == null) {
var nativeTextField = (UITextField)Control;
nativeTextField.BackgroundColor = UIColor.Gray;
nativeTextField.BorderStyle = UITextBorderStyle.Line;
}
}
}
}
您可以在呈现器上执行几乎任何操作,因为您正在引用本机 API。如果您想要查看包含此代码段的示例,请参阅 bit.ly/1xTIjmR 上的“Xamarin.Forms 自定义呈现器”。
从头开始创建呈现器可以创建不扩展任何其他呈现器的全新呈现器。创建呈现器会需要您做更多的工作,但是这有益于执行以下任一操作:
替换视图的呈现器。
将新的视图类型添加到您的解决方案。
将本机控件或本机页面添加到您的解决方案。
例如,如果您想要将本机 UIView 控件添加到 iOS 版本应用的页面中,则应将自定义呈现器添加到您的 iOS 项目,如图 6 中所示。
图 6 将本机 UIView 控件添加到配备自定义呈现器的 iOS 应用
[assembly: ExportRendererAttribute(typeof(RoundedBoxView),
typeof(RoundedBoxViewRenderer))]
namespace RBVRenderer.iOS
{
public class RoundedBoxViewRenderer :
ViewRenderer<RoundedBoxView,UIView>
{
protected override void OnElementChanged(
ElementChangedEventArgs<RoundedBoxView> e)
{
base.OnElementChanged(e);
var rbvOld = e.OldElement;
if (rbvOld != null)
{
// Unhook any events from e.OldElement here.
}
var rbv = e.NewElement;
if (rbv != null)
{
var shadowView = new UIView();
// Set properties on the UIView here.
SetNativeControl(shadowView);
// Hook up any events from e.NewElement here.
}
}
}
}
此呈现器中显示的通用模式,可确保您可以在虚拟化布局(如列表视图)中使用此模式,稍后我将对此进行讨论。
如果您想要查看包含此代码段的示例,请参阅 bit.ly/xf-customrenderer。
将属性添加到自定义视图您可以将属性添加到自定义视图,但要确保这些属性可绑定,以便您可以将属性绑定到视图模型中的属性或其他类型的数据。下面是一个 RoundedBoxView 自定义视图中可绑定的属性:
public class RoundedBoxView : BoxView
{
public static readonly BindableProperty CornerRadiusProperty =
BindableProperty.Create<RoundedBoxView, double>(p => p.CornerRadius, 0);
public double CornerRadius
{
get { return (double)base.GetValue(CornerRadiusProperty);}
set { base.SetValue(CornerRadiusProperty, value);}
}
}
若要将新属性连接到您的呈现器,请重写呈现器的 OnElementPropertyChanged 方法,并添加在属性更改时运行的代码:
protected override void OnElementPropertyChanged(object sender,
System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName ==
RoundedBoxView.CornerRadiusProperty.PropertyName)
childView.Layer.CornerRadius = (float)this.Element.CornerRadius;
}
若要了解有关创建自定义视图和自定义呈现器的详细信息,请参阅 bit.ly/11pSFhL 上的“自定义每个平台的控件”。
我已经展示了几个元素,但还有更多。这是介绍这些元素的好时机。
Xamarin.Forms 应用包含页面、布局和视图。一个页面包含一个或多个布局,一个布局包含一个或多个视图。在 Xamarin 中使用术语视图来描述您调用控件的习惯。总的来说,Xamarin.Forms 框架包含五种页面类型、七种布局类型和 24 种视图类型。通过 xamarin.com/forms,您可以获得更多信息。稍后,我将介绍一些重要的页面类型,但首先我将花一点时间回顾一些您可以在应用中使用的布局。Xamarin.Forms 包含四种主要布局:
StackLayout:StackLayout 在单个垂直或水平行中定位子元素。您可以嵌套 StackLayouts 来创建复杂的可视层次结构。通过使用每个子视图的 VerticalOptions 和 Horizontal­Options 属性,可以控制视图在 StackLayout 中的排列方式。
网格:网格将视图排列入行和列。此布局类似于使用 WPF 和 Silverlight 获得的布局,但您不可以在行和列之间添加间距。通过使用网格的 RowSpacing 和 ColumnSpacing 属性来做到这一点。
RelativeLayout:通过使用相对于其他视图的约束,RelativeLayout 可以定位视图。
AbsoluteLayout:AbsoluteLayout 可以通过两种方式定位子视图:绝对位置定位或相对于父级按比例定位。这有助于创建拆分并叠加层次结构。图 7 显示了一个示例。
图 7 使用 AbsoluteLayout
void AbsoluteLayoutView()
{
var layout = new AbsoluteLayout();
var leftHalfOfLayoutChild = new BoxView { Color = Color.Red };
var centerAutomaticallySizedChild =
new BoxView { Color = Color.Green };
var absolutelyPositionedChild = new BoxView { Color = Color.Blue };
layout.Children.Add(leftHalfOfLayoutChild,
new Rectangle(0, 0, 0.5, 1),
AbsoluteLayoutFlags.All);
layout.Children.Add(centerAutomaticallySizedChild,
new Rectangle(
0.5, 0.5, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize),
AbsoluteLayoutFlags.PositionProportional);
layout.Children.Add(
absolutelyPositionedChild, new Rectangle(10, 20, 30, 40));
}
请注意,所有布局都为您提供了名为 Children 的属性。该属性可用于访问其他成员。例如,可以使用网格布局的 Children 属性来添加和删除行和列,以及指定行和列间距。
通过使用列表视图窗体(名为 ListView),可以在滚动列表中显示数据。此视图性能良好,因为列表中每个单元格的呈现器均被虚拟化。由于每个单元格均被虚拟化,因此通过使用与前面类似的模式,正确处理为单元格或列表创建的任何自定义呈现器的 OnElementChanged 事件是非常重要的。
首先,定义某一单元格,如图 8 中所示。ListView 的所有数据模板都必须都使用单元格作为根元素。
图 8 定义 ListView 单元格
public class MyCell : ViewCell
{
public MyCell()
{
var nameLabel = new Label();
nameLabel.SetBinding(Label.TextProperty, "Name");
var descLabel = new Label();
descLabel.SetBinding(Label.TextProperty, "Description");
View = new StackLayout
{
VerticalOptions = LayoutOptions.Center,
Children = { nameLabel, descLabel }
};
}
}
接下来,定义数据源,并对新的数据模板设置 ListView 的 ItemTemplate 属性。数据模板基于前面创建的 MyCell 类:
var items = new[] {
new { Name = "Flower", Description = "A lovely pot of flowers." },
new { Name = "Tuna", Description = "A can of tuna!" },
// ... Add more items
};
var listView = new ListView
{
ItemsSource = items,
ItemTemplate = new DataTemplate(typeof(MyCell))
};
您可以借助以下标记在 XAML 中执行此操作:
<ListView ItemsSource="{Binding Items}">
<ListView.ItemTemplate>
<ViewCell>
<StackLayout VerticalOptions="center">
<Label Text="{Binding Name}" />
<Label Text="{Binding Description}" />
</StackLayout>
</ViewCell>
</ListView.ItemTemplate>
</ListView>
大多数应用包含多个页面,因此您需要使用户能够从一个页面导航到另一个页面。以下页面具有适用于页面导航的内置支持,并支持全屏模式页面演示文稿:
TabbedPage
MasterDetailPage
NavigationPage
CarouselPage
您可以将页面作为子级添加到这四个页面的任何一个,并免费获得导航。
Tabbed Page TabbedPage 横跨屏幕顶部显示选项卡的数组。假设 PCL 项目包含名为 LogInPage、DirectoryPage 和 AboutPage 的页面,则可以使用以下代码将这些页面全部添加到 TabbedPage:
var tabbedPage = new TabbedPage
{
Children =
{
new LoginPage { Title = "Login", Icon = "login.png" },
new DirectoryPage { Title = "Directory", Icon = "directory.png" },
new AboutPage { Title = "About", Icon = "about.png" }
}
};
在这种情况下,设置每个页面的标题和图标属性是非常重要的,这可以使某些内容显示在页面选项卡上。并非所有平台都呈现图标。这取决于平台的选项卡设计。
如果您在移动设备上打开此页面,第一个选项卡将显示为选中状态。但是,可以通过设置 TabbedPage 页面的 CurrentPage 属性更改此状态。
NavigationPageNavigationPage 管理大量页面的导航和 UX。此页为您提供了最常见的移动应用导航模式类型。下面是如何向它添加您的页面:
var loginPage = new LoginPage();
var navigationPage = new NavigationPage(loginPage);
loginPage.LoginSuccessful += async (o, e) => await
navigationPage.PushAsync(new DirectoryPage());
请注意,PushAsync 方法用于导航用户到特定页面(在本例中为 DirectoryPage)。在 NavigationPage 中,可以将页面“推送”到堆栈,然后在用户向后导航到先前页面时将其“弹出”。
NavigationPage 的 PushAsync 和 PopAsync 方法是异步的,因此您的代码应等待它们,而不是运行任务时推送或弹出任何新页面。推送或弹出的动画完成后,返回每种方法的任务。
为方便起见,所有 Xamarin.Forms 视图、布局和页面都包含导航属性。此属性是一个代理接口,包含 NavigationPage 实例的 PushAsync 和 PopAsync 方法。该属性可用于导航到页面而不是直接调用 NavigationPage 实例的 PushAsync 和 PopAsync 方法。NavigationProperty 还可用于获取 PushModalAsync 和 PopModalAsync 方法。这有助于将整个屏幕的内容替换为新的模式页面。视图的父堆栈中不一定必须有一个 NavigationPage 来使用视图的导航属性,但无模式 PushAsync/PopAsync 操作可能会失败。
关于设计模式的注释通常,将 NavigationPages 作为子级添加到 TabbedPages,将 TabbedPages 作为子级添加到 MasterDetailPages。某些类型的模式可能会导致意外的 UX。例如,大多数平台建议您不要将 TabbedPage 添加为 NavigationPage 的子级。
有两种方法对页面上的视图设置动画效果,来创建更具吸引力的用户体验。选择 Xamarin.Forms 附带的内置动画,或通过使用动画 API 自己构建。
例如,您可以通过调用一个视图的 FadeTo 动画创建淡化效果。FadeTo 动画内置于视图中,因此简单易用:
async Task SpinAndFadeView(View view)
{
await view.FadeTo(20, length: 200, easing: Easing.CubicInOut);
}
可以通过使用 await 关键字一起链接一系列的动画。在前一个完成后,将执行每个动画。例如,可以在将视图淡化为焦点之前对其进行旋转:
async Task SpinAndFadeView(View view)
{
await view.RotateTo(180);
await view.FadeTo(20, length: 200, easing: Easing.CubicInOut);
}
如果在实现所需效果时遇到问题,可以使用完整的动画 API。在下面的代码中,通过旋转视图淡化一半:
void SpinAndFadeView(View view)
{
var animation = new Animation();
animation.Add(0, 1, new Animation(
d => view.Rotation = d, 0, 180, Easing.CubicInOut));
animation.Add(0.5, 1, new Animation(
d => view.Opacity = d, 1, 0, Easing.Linear));
animation.Commit(view, "FadeAndRotate", length: 250);
}
此示例将每个动画组合成单个动画实例,然后使用 Commit 方法运行整个动画序列。因为此动画不能局限于特定视图,所以您可以将此动画应用于任何视图。
Xamarin.Forms 是构建跨平台本机移动应用的令人激动的新方法。使用它可以构建跨 iOS、Android 和 Windows Phone 本机呈现的 UI。您可以在平台之间共享几乎所有代码。
Xamarin Inc. 构建 Xamarin 和 Xamarin.Forms,使 C# 开发人员几乎能够迅速跳转到移动开发。如果您已经为 Windows 运行时、WPF 或 Silverlight 进行开发,您会发现 Xamarin.Forms 是跨平台本机移动开发领域的便捷桥梁。您可以立即安装 Xamarin 并立即开始使用 C#,以构建在 iOS、Android 和 Windows Phone 设备上运行的美观本机应用。
看完上述内容,你们对如何借助Xamarin.Forms跨移动平台共享UI代码有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注亿速云行业资讯频道,感谢大家的支持。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
原文链接:https://my.oschina.net/u/3772973/blog/4631696