Summary of Chapter 2. Anatomy of an app
Note
This book was published in the spring of 2016, and has not been updated since then. There is much in the book that remains valuable, but some of the material is outdated, and some topics are no longer entirely correct or complete.
In a Xamarin.Forms application, objects that occupy space on the screen are known as visual elements, encapsulated by the VisualElement
class. Visual Elements can be split into three categories corresponding to these classes:
A Page
derivative occupies the entire screen, or nearly the entire screen. Often, the child of a page is a Layout
derivative to organize child visual elements. The children of the Layout
can be other Layout
classes or View
derivatives (often called elements), which are familiar objects such as text, bitmaps, sliders, buttons, list boxes, and so on.
This chapter demonstrates how to create an application by focusing on the Label
, which is the View
derivative that displays text.
With the Xamarin platform installed, you can create a new Xamarin.Forms solution in Visual Studio or Visual Studio for Mac. The Hello solution uses a Portable Class Library for the common code.
Note
Portable Class Libraries have been replaced by .NET Standard libraries. All the sample code from the book has been converted to use .NET standard libraries.
This sample demonstrates a Xamarin.Forms solution created in Visual Studio with no modifications. The solution consists of four projects:
- Hello, a Portable Class Library (PCL) shared by the other projects
- Hello.Droid, an application project for Android
- Hello.iOS, an application project for iOS
- Hello.UWP, an application project for the Universal Windows Platform (Windows 10 and Windows 10 Mobile)
Note
Xamarin.Forms no longer supports Windows 8.1, Windows Phone 8.1, or Windows 10 Mobile, but Xamarin.Forms applications do run on the Windows 10 desktop.
You can make any of these application projects the startup project, and then build and run the program on a device or simulator.
In many of your Xamarin.Forms programs, you won't be modifying the application projects. These often remain tiny stubs just to start up the program. Most of your focus will be the library common to all the applications.
The visuals displayed by the Hello program are defined in the constructor of the App
class. App
derives from the Xamarin.Forms class Application
.
Note
The Visual Studio solution templates for Xamarin.Forms create a page with a XAML file. XAML is not covered in this book until Chapter 7.
The References section of the Hello PCL project includes the following Xamarin.Forms assemblies:
- Xamarin.Forms.Core
- Xamarin.Forms.Xaml
- Xamarin.Forms.Platform
The References sections of the five application projects include additional assemblies that apply to the individual platforms:
- Xamarin.Forms.Platform.Android
- Xamarin.Forms.Platform.iOS
- Xamarin.Forms.Platform.UWP
- Xamarin.Forms.Platform.WinRT
- Xamarin.Forms.Platform.WinRT.Tablet
- Xamarin.Forms.Platform.WinRT.Phone
Note
The References sections of these projects no longer list the assemblies. Instead, the project file contains a PackageReference tags referencing the Xamarin.Forms NuGet package. The References section in Visual Studio lists the Xamarin.Forms package rather than the Xamarin.Forms assemblies.
Each of the application projects contains a call to the static Forms.Init
method in the Xamarin.Forms
namespace. This initializes the Xamarin.Forms library. A different version of Forms.Init
is defined for each platform. The calls to this method can be found in the following classes:
- iOS:
AppDelegate
- Android:
MainActivity
- UWP:
App
class,OnLaunched
method
In addition, each platform must instantiate the App
class location in the shared library. This occurs in a call to LoadApplication
in the following classes:
- iOS:
AppDelegate
- Android:
MainActivity
- UWP:
MainPage
Otherwise, these application projects are normal "do nothing" programs.
It's possible to create a Xamarin.Forms solution with the common code in either a Portable Class Library (PCL) or a Shared Asset Project (SAP). To create an SAP solution, select the Shared option in Visual Studio. The HelloSap solution demonstrates the SAP template with no modifications.
Note
Portable Class Libraries has been replaced by .NET Standard libraries. All the sample code from the book has been converted to use .NET standard libraries. Otherwise, the PCL and .NET Standard libraries are conceptually very similar.
The library approach bundles all the common code in a library project referenced by the platform application projects. With the SAP approach, the common code effectively exists in all the platform application projects and is shared among them.
Most Xamarin.Forms developers prefer the library approach. In this book, most of the solutions use a library. Those that use SAP include an Sap suffix in the project name.
With the SAP approach the code in the shared project can execute different code for the various platforms by using C# preprocessor directives (#if
, #elif
, and #endif
) with these predefined identifiers:
- iOS:
__IOS__
- Android:
__ANDROID__
- UWP:
WINDOWS_UWP
In a shared library, you can determine what platform you're running on at runtime, as you'll see later in this chapter.
The Greetings solution demonstrates how to add a new C# file to the Greetings project. This file defines a class named GreetingsPage
that derives from ContentPage
. In this book, most projects contain a single ContentPage
derivative whose name is the name of the project with the suffix Page
appended.
The GreetingsPage
constructor instantiates a Label
view, which is the Xamarin.Forms view that displays text. The Text
property is set to the text displayed by the Label
. This program sets the Label
to the Content
property of ContentPage
. The constructor of the App
class then instantiates GreetingsPage
and sets it to its MainPage
property.
The text is displayed in the upper-left corner of the page. On iOS, this means that it overlaps the page's status bar. There are several solutions to this problem:
Set a Padding
property on the page. Padding
is of type Thickness
, a structure with four properties:
Padding
defines an area inside a page where content is excluded. This allows the Label
to avoid overwriting the iOS status bar.
Set a 'Padding' property only on iOS using an SAP with a C# preprocessor directive. This is demonstrated in the GreetingsSap solution.
In the version of Xamarin.Forms used for the book, a Padding
property specific to iOS in either a PCL or SAP can be selected using the Device.OnPlatform
or Device.OnPlatform<T>
static method. These methods are now deprecated
The Device.OnPlatform
methods are used to run platform-specific code or to select platform-specific values. Internally, they make use of the Device.OS
static read-only property, which returns a member of the TargetPlatform
enumeration:
The Device.OnPlatform
methods, the Device.OS
property, and the TargetPlatform
enumeration are all now deprecated. Instead, use the Device.RuntimePlatform
property and compare the string
return value with the following static fields:
iOS
, the string "iOS"Android
, the string "Android"UWP
, the string "UWP", referring to the Universal Windows Platform
The Device.Idiom
static read-only property is related. This returns a member of the TargetIdiom
, which has these members:
Desktop
Tablet
Phone
Unsupported
is unused
For iOS and Android, the cutoff between Tablet
and Phone
is a portrait width of 600 units. For the Windows platform, Desktop
indicates a UWP application running under Windows 10, and Phone
indicates a UWP application running under Windows 10 application.
The Margin
property was introduced too late to be included in the book, but it is also of type Thickness
and you can set it on the Label
to define an area outside the view that is included in the calculation of the view's layout.
The Padding
property is only available on Layout
and Page
derivatives. The Margin
property is available on all View
derivatives.
You can center the Label
within the Page
(or put it in one of eight other places) by setting the HorizontalOptions
and VerticalOptions
properties of the Label
to a value of type LayoutOptions
. The LayoutOptions
structure defines two properties:
An
Alignment
property of typeLayoutAlignment
, an enumeration with four members:Start
, which means left or top depending on the orientation,Center
,End
, which means right or bottom depending on the orientation, andFill
.An
Expands
property of typebool
.
Generally these properties are not used directly. Instead, combinations of these two properties are provided by eight static read-only properties of type LayoutOptions
:
LayoutOptions.Start
LayoutOptions.Center
LayoutOptions.End
LayoutOptions.Fill
LayoutOptions.StartAndExpand
LayoutOptions.CenterAndExpand
LayoutOptions.EndAndExpand
LayoutOptions.FillAndExpand
HorizontalOptions
and VerticalOptions
are the most important properties in Xamarin.Forms layout, and are discussed in more detail in Chapter 4. Scrolling the Stack.
Here's the result with the HorizontalOptions
and VerticalOptions
properties of Label
both set to LayoutOptions.Center
:
You can also center the text (or place it in eight other locations on the page) by setting the HorizontalTextAlignment
and VerticalTextAlignment
properties of Label
to a member of the TextAlignment
enumeration:
Start
, meaning left or top (depending on orientation)Center
End
, meaning right or bottom (depending on orientation)
These two properties are defined only by Label
, whereas the HorizontalAlignment
and VerticalAlignment
properties are defined by View
and inherited by all View
derivatives. The visual results might seem similar, but they are very different as the next chapter demonstrates.