Xamarin.Forms快速入门-深入探讨
项目介绍
以Notes项目为例,The Notes application consists of one solution containing four projects, as shown in the following screenshot:
The projects are:
- Notes – This project is the .NET Standard library project that holds all of the shared code and shared UI.【包含所有共享代码和共享 UI 的 .NET Standard 库项目】
- Notes.Android – This project holds Android-specific code and is the entry point for the Android application.
- Notes.iOS – This project holds iOS-specific code and is the entry point for the iOS application.
- Notes.UWP – This project holds Universal Windows Platform (UWP) specific code and is the entry point for the UWP application.
程序剖析
1、.NET Standard 库项目
包含 NuGet 和 SDK :
- NuGet–已添加到项目的 Xamarin 和 sqlite-pcl NuGet 包。
- SDK –
NETStandard.Library
元包。
2、项目还包括多个文件:
- Data\NoteDatabase.cs –此类包含用于创建数据库、从中读取数据、向其中写入数据和从中删除数据的代码。
- Models\Note.cs –此类定义一个
Note
模型, 其实例存储有关应用程序中每个注释的数据。 - App.xaml -
App
类的 XAML 标记,该类定义应用程序的资源字典。 - App.xaml.cs -
App
类的代码隐藏,该类负责实例化应用程序在每个平台上将显示的首页,并处理应用程序生命周期事件。 - AssemblyInfo.cs –此文件包含项目的应用程序属性, 该属性应用于程序集级别。
- NotesPage -
NotesPage
类的 xaml 标记, 用于定义在应用程序启动时显示的页的 UI。 - NotesPage.xaml.cs -
NotesPage
类的代码隐藏, 该类包含用户与页面交互时执行的业务逻辑。 - NoteEntryPage -
NoteEntryPage
类的 xaml 标记, 它定义用户输入备注时显示的页面的 UI。 - NoteEntryPage.xaml.cs -
NoteEntryPage
类的代码隐藏, 该类包含用户与页面交互时执行的业务逻辑。
体系结构和应用程序基础知识
共享代码通常位于 .NET Standard 库中,平台特定应用程序将使用此共享代码。
- App.xaml
若要最大限度重用启动代码,Xamarin.Forms 应用程序需有一个名为 App
的单个类,该类负责实例化应用程序在每个平台上将显示的首页【MainPage】:MainPage = new NavigationPage(new NotesPage());
- AssemblyInfo.cs
包含项目的应用程序属性。XamlCompilation
特性用于控制在生成时还是运行时编译 XAML , 以便将 xaml 直接编译为中间语言。
启动应用程序
- IOS
若要在 iOS 中启动最初的Xamarin. Forms 页面, Notes.ios 项目定义了从FormsApplicationDelegate
类继承的AppDelegate
类。
namespace Notes.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); } } }
重写FinishedLaunching
方法中,通过调用Init方法来初始化 Xamarin.Forms framework ,这导致了Xamarin的ios特定实现在 根视图控制器(通过LoadApplication方法调用)之前加载。
- Android
若要在 Android 中启动最初的 Xamarin. Forms 页面, Notes.android 项目包含了一个带MainLauncher
属性的Activity
,此Activity从FormsAppCompatActivity
类继承:
namespace Notes.Droid { [Activity(Label = "Notes", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)] public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity { protected override void OnCreate(Bundle savedInstanceState) { TabLayoutResource = Resource.Layout.Tabbar; ToolbarResource = Resource.Layout.Toolbar; base.OnCreate(savedInstanceState); Xamarin.Essentials.Platform.Init(this, savedInstanceState); global::Xamarin.Forms.Forms.Init(this, savedInstanceState); LoadApplication(new App()); } } }
重写OnCreate方法中,通过调用Init方法来初始化 Xamarin.Forms framework ,这导致了Xamarin的android特定实现在 根视图控制器(通过LoadApplication方法调用)之前加载。
- 通用 Windows 平台(UWP)
从 App 类调用初始化 Xamarin.Forms 框架的 Init 方法(将特定于 UWP 的 Xamarin.Forms 实现加载到应用程序)
初始Xamarin.Forms页由MainPage类启动,再加载 Xamarin.Forms 应用程序(App.Xaml) 。
Universal Windows Platform apps can be built with Xamarin.Forms, but only using Visual Studio on Windows.
用户界面
有四个主要的控件组:
- 页面 - Xamarin.Forms 页呈现跨平台移动应用程序屏幕。 Notes 应用程序使用
ContentPage
类(继承它)显示单个屏幕。 有关页面的详细信息,请参阅 Xamarin.Forms 页面。 - 视图 - Xamarin.Forms 视图是显示在用户界面上的控件,如标签、按钮和文本输入框,程序中对应
ListView
、Editor
和Button
。 有关视图的详细信息,请参阅 Xamarin.Forms 视图。 - 布局 - Xamarin.Forms 布局是用于将视图组合到逻辑结构的容器。 Notes 应用程序使用
StackLayout
类在垂直堆栈中排列视图和Grid
类来水平排列按钮。 有关布局的详细信息,请参阅 Xamarin.Forms 布局。 - 单元格 - Xamarin.Forms 单元格是用于列表中项的专门元素,描述列表中每个项的绘制方式。 Notes 应用程序使用
TextCell
为列表中的每一行显示两个项。 有关单元格的详细信息,请参阅 Xamarin.Forms 单元格。
在运行时,每个控件都会映射到其本身的本机等效项(即呈现的内容)。
- 布局
Notes 应用程序使用StackLayout
来简化跨平台应用程序开发, 而不考虑屏幕大小。 根据添加顺序,以垂直方式或水平方式逐个放置每个子元素。 StackLayout
使用的空间大小取决于 HorizontalOptions
和 VerticalOptions
属性的设置方式,但默认情况下,StackLayout
尝试使用整个屏幕。
默认情况下StackLayout
,为垂直方向。 但是, 可以通过改StackLayout.Orientation
属性为水平方向。
可以通过HeightRequest
和WidthRequest
属性设置视图的大小。
- 响应用户交互
XAML 中定义的对象可触发在cs文件中处理的事件。
导航Navigation
Xamarin.Forms 提供多种不同的页导航体验,具体取决于使用的 Page
类型。对于ContentPage
实例, 导航可以是分层的, 也可以是模式。 有关模式导航的信息, 请参阅Xamarin. Forms 模式页面。
注:CarouselPage、
MasterDetailPage
和 TabbedPage
类提供替代导航体验。 有关详细信息,请参阅导航。
NavigationPage
在层次结构导航【分层导航】中 NavigationPage
类用于根据需要,在ContentPage
对象堆栈中向前和向后导航。 此类将导航实现为 Page
对象的后进先出 (LIFO) 堆栈。 若要从一页移动到另一页,应用程序会将新页推送到导航堆栈中,在堆栈中,该页会变为活动页。 若要返回到前一页,应用程序会从导航堆栈弹出当前页,而使最顶层的页成为活动页。
NavigationPage
类还会将一个导航栏添加到页面顶部,此导航栏包括 标题和平台相应的“返回”按钮,通过此按钮可返回上一页。
页面跳转
所有 ContentPage
实例都具有 Navigation
属性,可提供修改页面堆栈的方法,
eg,从页面跳到其他页面,await Navigation.PushAsync(new NoteEntryPage()); //这将导致NoteEntryPage新
对象被推送到导航堆栈上, 并将其变成活动页。
通过设备上的返回按钮(无论是设备上的物理按钮还是屏幕按钮),可以从导航堆栈中弹出活动页。 若要以编程方式返回原始页,NoteEntryPage
对象必须调用 PopAsync
方法:await Navigation.PopAsync();
数据绑定
数据绑定在用户界面和应用程序之间建立连接。
参考:Xamarin.From中的Data binding(数据绑定)(一)
数据绑定连接两个对象,即源和目标。 源对象提供数据, 目标对象使用(并经常显示)来自源对象的数据。 例如, Editor
(目标对象) 通常会将Text
属性绑定到源对象中string
的属性。 下图说明了这种绑定关系:
数据绑定的主要优点是让你无需再担心视图和数据源之间的数据同步。 底层的绑定框架源会将源对象中的更改自动推送到目标对象,且目标对象中的更改可选择性地推送回源对象。
建立数据绑定的过程分为两个步骤:
- 目标对象的
BindingContext
属性必须设置为源。 - 必须在目标和源之间建立绑定。
实现绑定有两种方式:在xaml或者cs中
每种又分使用BindingContext与否。
1、在 XAML 中【常用方式】
不使用BingingContext:可通过使用 Binding
标记扩展实现。
在 Notes 应用程序中, 绑定目标Editor用于
显示note, 而NoteEntryPage设置的
绑定源。BindingContext即N
ote对象
是
await Navigation.PushAsync(new NoteEntryPage { BindingContext = new Note() });
NoteEntryPage页面中Editor然后绑定Note对象的Text属性:
<Editor Placeholder="Enter your note" Text="{Binding Text}" ... />
在 Editor.Text
属性(目标)和源对象(Note实例)的 Text
属性之间建立绑定。 在Editor中所做
的更改会自动传播到Note
对象。 同样, 如果对Note.Text
属性进行了更改, Xamarin 绑定引擎也将更新Editor的内容,这称为双向绑定。
使用BingingContext:
BindingContext="{x:Reference Name=slider}"
Rotation="{Binding Path=Value}"/>
小结:将Binding的Source属性或者BindingContext属性设置为x:Reference标记扩展,以引用页面上的另一个视图(源对象)。 这两个属性的类型为Object,可以将它们设置为任何包含适合于绑定源的属性的对象。
如果两者都已设置,则 Binding
的 Source
属性优先于 BindingContext
。
2、只在cs中设定
需要设置以下
BindingContext
属性指定源对象。SetBinding
方法指定目标属性和源属性。
public BasicCodeBindingPage() { InitializeComponent(); label.BindingContext = slider; label.SetBinding(Label.RotationProperty, "Value"); }
注:若 目标和源 都是控件,则可以完全在xaml中实现绑定:
<StackLayout Padding="10, 0"> <Label x:Name="label" Text="TEXT" FontSize="80" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" BindingContext="{x:Reference Name=slider}" Rotation="{Binding Path=Value}" /> <Slider x:Name="slider" Maximum="360" VerticalOptions="CenterAndExpand" /> </StackLayout>
可以简化“基本 XAML 绑定” 页上显示的标记:XAML 标记扩展名(如 x:Reference
和 Binding
)可以定义“内容属性” 属性,对于 XAML 标记扩展,这意味着不需要出现属性名称。 Name
属性是 x:Reference
的内容属性,Path
属性是 Binding
的内容属性,这意味着可以从表达式中删除它们:
<Label Text="TEXT" FontSize="80" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" BindingContext="{x:Reference slider}" Rotation="{Binding Value}" />
更多参考:基本绑定
样式Styling
Xamarin.forms应用程序通常包含多个具有相同外观的视觉元素。 设置每个视觉对象的外观可能是重复性的并且容易出错。 相反, 可以创建用于定义外观的样式, 然后将其应用于所需的视觉对象。
Style
类将一些属性值分组到一个对象中, 然后可以将该对象应用于多个视觉元素实例。 样式存储在ResourceDictionary,可以针对
应用程序级别、页面级别或视图级别。 使用范围如下:
Style
instances defined at the application level can be applied throughout the application. 【应用程序级别定义的style 可以在整个应用程序中使用】Style
instances defined at the page level can be applied to the page and to its children.【页面级别定义的style 可以在此页面或者其子页面中使用,eg: <Style TargetType="{x:Type ContentPage}"】Style
instances defined at the view level can be applied to the view and to its children.【视图级别定义的style 可以在此视图或者子视图使用,eg:<Style TargetType="{x:Type Editor}">】
注:在整个应用程序中使用的所有样式均存储在应用程序的ResourceDictionary中, 以避免重复。 但是,XAML中的应用程序的ResourceDictionary中不应包含 用于特定于页面的Style, 因为在应用程序启动时将分析资源,而不是在页需要时进行分析。
每个Style
实例都包含一个或多个Setter
对象的集合。Setter
每个对象都有一个Property
和一个Value
。 属性是应用样式的元素的可绑定属性的名称,值是应用于属性的值。
eg:NoteEntryPage页面中的定义的Style
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Notes.NoteEntryPage" Title="Note Entry"> <ContentPage.Resources> <!-- Implicit styles --> <Style TargetType="{x:Type Editor}"> <Setter Property="BackgroundColor" Value="{StaticResource AppBackgroundColor}" /> </Style> ... </ContentPage.Resources> ... </ContentPage>
TargetType为Editor,表示NoteEntryPage页面中所有的Editor都适用于此样式。
注:除了可以使用XAMl样式,也还支持CSS样式。 请参阅设置使用级联样式表 (CSS) 的 Xamarin 应用程序样式。
提供特定于平台的样式
OnPlatform
标记扩展允许你根据每个平台自定义 UI 外观:
<Application xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Notes.App"> <Application.Resources> ... <Color x:Key="iOSNavigationBarColor">WhiteSmoke</Color> <Color x:Key="AndroidNavigationBarColor">#2196F3</Color> <Color x:Key="iOSNavigationBarTextColor">Black</Color> <Color x:Key="AndroidNavigationBarTextColor">White</Color> <Style TargetType="{x:Type NavigationPage}"> <Setter Property="BarBackgroundColor" Value="{OnPlatform iOS={StaticResource iOSNavigationBarColor}, Android={StaticResource AndroidNavigationBarColor}}" /> <Setter Property="BarTextColor" Value="{OnPlatform iOS={StaticResource iOSNavigationBarTextColor}, Android={StaticResource AndroidNavigationBarTextColor}}" /> </Style> ... </Application.Resources> </Application>