在 Xamarin.Forms 快速入门中,生成了 Phoneword 应用程序。 本文回顾生成的内容,以深入了解有关 Xamarin.Forms 应用程序工作原理的基础知识。
探讨了以下主题:
- Visual Studio 简介 - Visual Studio 以及创建新 Xamarin.Forms 应用程序的简介。
- Xamarin.Forms 应用程序剖析 - Xamarin.Forms 应用程序基本部分的教程。
- 体系结构和应用程序基础知识 - 每个平台启动应用程序的方式。
- 用户界面 (UI) - 创建 Xamarin.Forms 的用户界面。
- Phoneword 中引入的其他概念 - 简单介绍 Phoneword 应用程序使用的其他概念。
- 测试和部署 - 完成应用程序,并提供有关测试、部署、生成图稿等方面的建议。
Visual Studio 简介
Visual Studio 是 Microsoft 提供的强大 IDE。 它采用完全集成的可视化设计器、包含重构工具的文本编辑器、程序集浏览器、源代码集成等。 本文重点介绍如何通过 Xamarin 插件使用 Visual Studio 的一些基本功能。
Visual Studio 将代码组织为解决方案和项目。 解决方案是可以容纳一个或多个项目的容器。 项目可以是应用程序、支持库、测试应用程序等。 Phoneword 应用程序包含 1 个内附 6 个项目的解决方案,如以下屏幕截图所示。
这些项目如下:
- Phoneword - 此项目是可移植类库 (PCL) 项目,其中包含所有共享代码和共享 UI。
- Phoneword.Droid - 此项目包含 Android 特定代码,是 Android 应用程序的入口点。
- Phoneword.iOS - 此项目包含 iOS 特定代码,是 iOS 应用程序的入口点。
- Phoneword.UWP - 此项目包含通用 Windows 平台特定代码,是 UWP 应用程序的入口点。
- Phoneword.WinPhone - 此项目包含 Windows Phone 特定代码,是 Windows Phone 8.0 应用程序的入口点。
- Phoneword.WinPhone81 - 此项目包含 Windows Phone 8.1 特定代码,是 Windows Phone 8.1 应用程序的入口点。
Xamarin.Forms 应用程序剖析
以下屏幕截图显示 Visual Studio 中 Phoneword PCL 项目的内容:
项目包含 2 个文件夹:
- 引用 - 包含生成和运行应用程序所需的程序集。
- 属性 - 包含 .NET 程序集元数据文件 AssemblyInfo.cs。 最好在此文件中填写一些应用程序相关的基本信息。 有关此文件的详细信息,请参阅 MSDN 上的 AssemblyInfo 类。
项目还包括多个文件:
- App.xaml -
类的 XAML 标记,该类定义应用程序的资源字典。App
- App.xaml.cs -
类的代码隐藏,该类负责实例化应用程序在每个平台上将显示的首页,并处理应用程序生命周期事件。App
- IDialer.cs< -
接口,该接口指定IDialer
方法必须由任何实现类提供。Dial
- MainPage.xaml -
类的 XAML 标记,该类定义应用程序启动时所显示页的 UI。MainPage
- MainPage.xaml.cs -
类的代码隐藏,该类包含用户与页面交互时执行的业务逻辑。MainPage
- packages.config - XML 文件,其中包含项目所使用 NuGet 包的相关信息,以便跟踪所需包及各自的版本。 Xamarin Studio 和 Visual Studio 均可配置为:与其他用户共享源代码时,自动还原任何缺少的 NuGet 包。 此文件的内容由 NuGet 包管理器控制,且不可手动编辑。
- PhoneTranslator.cs - 负责将电话文字转换为电话号码的业务逻辑,此逻辑从 MainPage.xaml.cs 调用。
有关 Xamarin.iOS 应用程序剖析的详细信息,请参阅 Xamarin.iOS 应用程序剖析。 有关 Xamarin.Android 应用程序剖析的详细信息,请参阅 Xamarin Android 应用程序剖析。
体系结构和应用程序基础知识
Xamarin.Forms 应用程序采用与传统跨平台应用程序相同的构建方式。 共享代码通常位于可移植类库 (PCL) 中,平台特定应用程序使用此共享代码。 下图概要演示了 Phoneword 应用程序的这种关系:
有关 PCL的详细信息,请参阅可移植类库简介。
若要最大限度重用启动代码,Xamarin.Forms 应用程序需有一个名为
App
的单个类,该类负责实例化应用程序在每个平台上将显示的首页,如以下代码示例所示:
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace Phoneword
{
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new MainPage();
}
...
}
}
此代码将
App
类的
MainPage
属性设置为
MainPage
类的一个新实例。 此外,
XamlCompilation
属性可打开 XAML 编译器,以使 XAML 直接编译为中间语言。 有关详细信息,请参阅 XAML 编译。
在每个平台上启动应用程序
iOS
若要在 iOS 中启动 Xamarin.Forms 初始页面,Phoneword.iOS 项目应包括继承自
FormsApplicationDelegate
类的
AppDelegate
类,如以下代码示例所示:
namespace Phoneword.iOS
{
[Register ("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init ();
LoadApplication (new App ());
return base.FinishedLaunching (app, options);
}
}
}
通过调用
Init
方法,
FinishedLaunching
替代初始化 Xamarin.Forms 框架。 这会导致在调用将根视图控制器设置为
LoadApplication
方法之前,将特定于 iOS 的 Xamarin.Forms 实现加载到应用程序。
Android
若要在 Android 中启动 Xamarin.Forms 初始页面,Phoneword.Droid 项目应包括使用
MainLauncher
属性创建活动的代码,以及继承自
FormsApplicationActivity
类的活动,如以下代码示例所示:
namespace Phoneword.Droid
{
[Activity (Label = "Phoneword.Droid",
Icon = "@drawable/icon",
MainLauncher = true,
ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity
{
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
global::Xamarin.Forms.Forms.Init (this, bundle);
LoadApplication (new App ());
}
}
}
通过调用
Init
方法,
OnCreate
替代初始化 Xamarin.Forms 框架。 这会导致在加载 Xamarin.Forms 应用程序之前,将特定于 Android 的 Xamarin.Forms 实现加载到应用程序。
通用 Windows 平台
在通用 Windows 平台 (UWP) 应用程序中,可从
App
类调用初始化 Xamarin.Forms 框架的
Init
方法:
Xamarin.Forms.Forms.Init (e);
if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
...
}
这会将特定于 UWP 的 Xamarin.Forms 实现加载到应用程序。 可通过
MainPage
类启动 Xamarin.Forms 初始页面,如以下代码示例所示:
namespace Phoneword.UWP
{
public sealed partial class MainPage
{
public MainPage()
{
this.InitializeComponent();
this.LoadApplication(new Phoneword.App());
}
}
}
可通过
LoadApplication
方法加载 Xamarin.Forms 应用程序。
用户界面
可使用 4 个主要控件组创建 Xamarin.Forms 应用程序的用户界面。
- 页面 - Xamarin.Forms 页呈现跨平台移动应用程序屏幕。 Phoneword 应用程序使用
类显示单个屏幕。 有关页面的详细信息,请参阅 Xamarin.Forms 页面。ContentPage
- 布局 - Xamarin.Forms 布局是用于将视图组合到逻辑结构的容器。 Phoneword 应用程序使用
类以水平堆叠方式排列控件。 有关布局的详细信息,请参阅 Xamarin.Forms 布局。StackLayout
- 视图 - Xamarin.Forms 视图是显示在用户界面上的控件,如标签、按钮和文本输入框。 Phoneword 应用程序使用
、Label
和Entry
控件。 有关视图的详细信息,请参阅 Xamarin.Forms 视图。Button
- 单元格 - Xamarin.Forms 单元格是专门用于列表中的项的元素,描述列表中每个项的绘制方式。 Phoneword 应用程序不会使用任何单元格。 有关单元格的详细信息,请参阅 Xamarin.Forms 单元格。
在运行时,每个控件都会映射到其本身的本机等效项(即呈现的内容)。
在任一平台运行 Phoneword 应用程序时,此应用会显示对应于 Xamarin.Forms 中
Page
的单一屏幕。
Page
在 Android 中表示为一个 ViewGroup,在 iOS 中表示为视图控制器,在 Windows 通用平台中则表示为一个页面。 Phoneword 应用程序也会实例化表示
MainPage
类的
ContentPage
对象,该类的 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="Phoneword.MainPage">
...
<ContentPage.Content>
<StackLayout VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand"
Orientation="Vertical"
Spacing="15">
<Label Text="Enter a Phoneword:" />
<Entry x:Name="phoneNumberText" Text="1-855-XAMARIN" />
<Button x:Name="translateButon" Text="Translate" Clicked="OnTranslate" />
<Button x:Name="callButton" Text="Call" IsEnabled="false" Clicked="OnCall" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
MainPage
类使用
StackLayout
控件在屏幕上自动排列控件,而不考虑屏幕大小。 根据添加顺序,以垂直方式逐个放置每个子元素。
StackLayout
占用的屏幕空间大小取决于
HorizontalOptions
的值和
VerticalOptions
属性。 在此情况下,
FillAndExpand
值指示
StackLayout
本身未进行填充,但进行了扩展。
StackLayout
控件包含 1 个用于在页面上显示文本的
Label
控件、1 个用于接收文本用户输入的
Entry
控件和 2 个用于在响应触摸事件时执行代码的
Button
控件。
有关 Xamarin.Forms 中 XAML 的详细信息,请参阅 Xamarin.Forms XAML 基础知识。
响应用户交互
XAML 中定义的对象可触发在隐藏文件中处理的事件。 以下代码示例演示了
MainPage
类的代码隐藏中的
OnTranslate
方法,该类在响应
Clicked
事件触发“转换”按钮时执行。
void OnTranslate(object sender, EventArgs e)
{
translatedNumber = Core.PhonewordTranslator.ToNumber (phoneNumberText.Text);
if (!string.IsNullOrWhiteSpace (translatedNumber)) {
callButton.IsEnabled = true;
callButton.Text = "Call " + translatedNumber;
} else {
callButton.IsEnabled = false;
callButton.Text = "Call";
}
}
OnTranslate
方法将 phoneword 转换为其相应的电话号码,并在响应时设置调用按钮上的属性。 XAML 类的代码隐藏文件可使用为其分配的、具有
x:Name
属性的名称访问 XAML 中定义的对象。 分配给此属性的值与 C# 变量的规则相同,因为该值必须以字母或下划线开头,且不包含嵌入的空格。
对
OnTranslate
方法的切换按钮布线会在
MainPage
类的 XAML 标记中出现:
<Button x:Name="translateButon" Text="Translate" Clicked="OnTranslate" />
Phoneword 中引入的其他概念
用于 Xamarin.Forms 的 Phoneword 应用程序引入了多个本文未提及的概念。 这些概念包括:
- 启用和禁用按钮。 通过更改
的Button
属性,可将其打开或关闭。 例如,以下代码示例禁用IsEnabled
:callButton
callButton.IsEnabled = false;
- 显示警报对话框。 用户按呼叫按钮时,Phoneword 应用程序会显示“警报”对话框,其中包含发出或取消呼叫的选项。
方法用于创建该对话框,如以下代码示例所示:DisplayAlert
await this.DisplayAlert ( "Dial a Number", "Would you like to call " + translatedNumber + "?", "Yes", "No");
- 通过
类访问本机功能。 Phoneword 应用程序使用DependencyService
类将DependencyService
接口解析到特定于平台的电话拨号实现中,如以下 Phoneword 项目中的代码示例所示:IDialer
有关async void OnCall (object sender, EventArgs e) { ... var dialer = DependencyService.Get<IDialer> (); ... }
类的详细信息,请参阅通过 DependencyService 访问本机功能。DependencyService
- 通过 URL 发出电话呼叫。 Phoneword 应用程序使用
启动系统电话应用。 URL 包含OpenURL
前缀,后跟要呼叫的电话号码,如以下 iOS 项目中的代码示例所示:tel:
return UIApplication.SharedApplication.OpenUrl (new NSUrl ("tel:" + number));
- 调整平台布局。 使用
类,开发人员能够根据每个平台自定义应用程序布局和功能,如以下代码示例所示(此示例使用 iOS 上的另一个Device
值正确显示每一页):Padding
有关平台调整的详细信息,请参阅设备类。<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" ...> <ContentPage.Padding> <OnPlatform x:TypeArguments="Thickness" iOS="20, 40, 20, 20" ... /> </ContentPage.Padding> ... </ContentPage>
测试和部署
Xamarin Studio 和 Visual Studio 均提供许多用于测试和部署应用程序的选项。 调试应用程序是应用程序开发生命周期的普遍一环,有助于诊断代码问题。 有关详细信息,请参阅设置断点、逐步执行代码和日志窗口的输出信息。
模拟器是开始部署和测试应用程序的有利位置,其提供用于测试应用程序的有用功能。 但是,用户不会在模拟器中使用最终应用程序,因此应尽早并经常在实际设备上测试应用程序。 有关 iOS 设备预配的详细信息,请参阅设备预配。 有关 Android 设备预配的详细信息,请参阅设置设备进行开发。
摘要
本文介绍了使用 Xamarin.Forms 开发应用程序的基础知识。 涵盖的主题包括:Xamarin.Forms 应用程序剖析、体系结构和应用程序基础知识以及用户界面。
在本指南的下一部分,将介绍如何扩展应用程序以包含多个屏幕,从而探索更高级的 Xamarin.Forms 体系结构和概念。