今天就跟大家聊聊有关如何借助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代码有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注亿速云行业资讯频道,感谢大家的支持。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。