Clearly, the program created by the Xamarin.Forms template is very simple, so this is an excellent op-portunity to examine the generated code files and figure out their interrelationships and how they work.
Let’s begin with the code that’s responsible for drawing the text that you see on the screen. This is the App class in the Hello project. In a project created by Visual Studio, the App class is defined in the App.cs file, but in Xamarin Studio, the file is Hello.cs. If the project template hasn’t changed too much since this chapter was written, it probably looks something like this:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Xamarin.Forms; namespace Hello { public class App : Application { public App() { // The root page of your application MainPage = new ContentPage { Content = new StackLayout { VerticalOptions = LayoutOptions.Center, Children = { new Label { HorizontalTextAlignment = TextAlignment.Center, Text = "Welcome to Xamarin Forms!" } } } }; } protected override void OnStart() { // Handle when your app starts } protected override void OnSleep() { // Handle when your app sleeps } protected override void OnResume() { // Handle when your app resumes } } }
Notice that the namespace is the same as the project name. This App class is defined as public and derives from the Xamarin.Forms Application class. The constructor really has just one responsibility: to set the MainPage property of the Application class to an object of type Page.
The code that the Xamarin.Forms template has generated here shows one very simple approach to defining this constructor: The ContentPage class derives from Page and is very common in single-page Xamarin.Forms applications. (You’ll see a lot of ContentPage throughout this book.) It occupies most of the phone’s screen with the exception of the status bar at the top of the Android screen, the buttons on the bottom of the Android screen, and the status bar at the top of the Windows Phone screen. (As you’ll discover, the iOS status bar is actually part of the ContentPage in single-page applications.)
The ContentPage class defines a property named Content that you set to the content of the page. Generally this content is a layout that in turn contains a bunch of views, and in this case it’s set to a StackLayout, which arranges its children in a stack.
This StackLayout has only one child, which is a Label. The Label class derives from View and is used in Xamarin.Forms applications to display up to a paragraph of text. The VerticalOptions and HorizontalTextAlignment properties are discussed in more detail later in this chapter.
For your own single-page Xamarin.Forms applications, you’ll generally be defining your own class that derives from ContentPage. The constructor of the App class then sets an instance of the class that you define to its MainPage property. You’ll see how this works shortly.
In the Hello solution, you’ll also see an AssemblyInfo.cs file for creating the PCL and a pack-ages.config file that contains the NuGet packages required by the program. In the References section under Hello in the solution list, you’ll see at least the four libraries this PCL requires:
- .NET (displayed as .NET Portable Subset in Xamarin Studio)
- Xamarin.Forms.Core
- Xamarin.Forms.Xaml
- Xamarin.Forms.Platform
It is this PCL project that will receive the bulk of your attention as you’re writing a Xamarin.Forms application. In some circumstances the code in this project might require some tailoring for the various platforms, and you’ll see shortly how to do that. You can also include platform-specific code in the five application projects.
The five application projects have their own assets in the form of icons and metadata, and you must pay particular attention to these assets if you intend to bring the application to market. But during the time that you’re learning how to develop applications using Xamarin.Forms, these assets can generally be ignored. You’ll probably want to keep these application projects collapsed in the solution list be-cause you don’t need to bother much with their contents.
But you really should know what’s in these application projects, so let’s take a closer look.
In the References section of each application project, you’ll see references to the common PCL pro-ject (Hello in this case), as well as various .NET assemblies, the Xamarin.Forms assembles listed above, and additional Xamarin.Forms assemblies applicable to each platform:
- Xamarin.Forms.Platform.Android
- Xamarin.Forms.Platform.iOS
- Xamarin.Forms.Platform.UAP (not explicitly displayed in the UWP project)
- Xamarin.Forms.Platform.WinRT
- Xamarin.Forms.Platform.WinRT.Tablet
- Xamarin.Forms.Platform.WinRT.Phone
Each of these libraries defines a static Forms.Init method in the Xamarin.Forms namespace that initializes the Xamarin.Forms system for that particular platform. The startup code in each platform must make a call to this method.
You’ve also just seen that the PCL project derives a public class named App that derives from Application. The startup code in each platform must also instantiate this App class.
If you’re familiar with iOS, Android, or Windows Phone development, you might be curious to see how the platform startup code handles these jobs.
The iOS project
An iOS project typically contains a class that derives from UIApplicationDelegate. However, the Xamarin.Forms.Platform.iOS library defines an alternative base class named FormsApplicationDele-gate. In the Hello.iOS project, you’ll see this AppDelegate.cs file, here stripped of all extraneous using directives and comments:
using Foundation; using UIKit; namespace Hello.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); } } }
The FinishedLaunching override begins by calling the Forms.Init method defined in the Xamarin.Forms.Platform.iOS assembly. It then calls a LoadApplication method (defined by the FormsApplicationDelegate), passing to it a new instance of the App class defined in the Hello namespace in the shared PCL. The page object set to the MainPage property of this App object can then be used to create an object of type UIViewController, which is responsible for rendering the page’s contents.
The Android project
In the Android application, the typical MainActivity class must be derived from a Xamarin.Forms class named FormsApplicationActivity, defined in the Xamarin.Forms.Platform.Android assem-bly, and the Forms.Init call requires some additional information:
using Android.App; using Android.Content.PM; using Android.OS; namespace Hello.Droid { [Activity(Label = "Hello", 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()); } } }
The new instance of the App class in the Hello namespace is then passed to a LoadApplication method defined by FormsApplicationActivity. The attribute set on the MainActivity class indi-cates that the activity is not re-created when the phone changes orientation (from portrait to land-scape or back) or the screen changes size.
The Universal Windows Platform project
In the UWP project (or either of the two Windows projects), look first in the App.xaml.cs file tucked un-derneath the App.xaml file in the project file list. In the OnLaunched method you will see the call to Forms.Init using the event arguments: Xamarin.Forms.Forms.Init(e);
Now look at the MainPage.xaml.cs file tucked underneath the MainPage.xaml file in the project file list. This file defines the customary MainPage class, but it actually derives from a Xamarin.Forms class spec-ified as the root element in the MainPage.xaml file. A newly instantiated App class is passed to the LoadApplication method defined by this base class:
namespace Hello.UWP { public sealed partial class MainPage { public MainPage() { this.InitializeComponent(); LoadApplication(new Hello.App()); } } }
Nothing special!
If you’ve created a Xamarin.Forms solution under Visual Studio and don’t want to target one or more platforms, simply delete those projects.
If you later change your mind about those projects—or you originally created the solution in Xamarin Studio and want to move it to Visual Studio to target one of the Windows platforms—you can add new platform projects to the Xamarin.Forms solution. In the Add New Project dialog, you can create a Unified API (not Classic API) Xamarin.iOS project by selecting the iOS project Universal type and Blank App template. Create a Xamarin.Android project with the Android Blank App template, or a Windows project by selecting Universal under the Windows heading (for a UWP project), or Windows or Windows Phone under the Windows 8 heading, and then Blank App.
For these new projects, you can get the correct references and boilerplate code by consulting the projects generated by the standard Xamarin.Forms template.
To summarize: there’s really nothing all that special in a Xamarin.Forms app compared with normal Xamarin or Windows Phone projects—except the Xamarin.Forms libraries.
I hope I have helped in something. Until the next opportunity!
Twittear
No hay comentarios:
Publicar un comentario