Cross Platform C#
Designing UIs for Multiple iOS 8 Devices
Even Apple devices aren't immune to the dreaded OS fragmentation problem. Thankfully, Xamarin has a solution, and Wally looks into it this month.
In September, Apple released the most recent version of iOS, iOS 8, and since then the iOS 8.1. The company also released two new phones -- the iPhone 6 with a 4.7-inch screen, and iPhone 6 Plus with a 5.5-inch screen -- and refreshed the iPad line with new versions of the iPad Air and iPad Mini. And those iPads, interestingly, have different screen resolutions and pixel densities than the iPhone. At the same time, Apple continues to sell older versions of its devices.
For developers, all these new releases represent the dreaded OS fragmentation that developers fear. How are developers going to handle the variations in old and new devices and screen sizes? Thankfully, Apple and Xamarin have thought this through and have created some flexible UI tools that I'll look at today:
- Storyboards: Storyboards allow a developer to create a single GUI design. This includes the screens, the individual screen layout and the flow between the screens. A unified storyboard is a storyboard layout for an application that works on both the iPhone and the iPad.
- Xamarin iOS Designer: The Xamarin iOS Designer is included with Xamarin.iOS. It runs on Mac with Xamarin Studio and Windows with Visual Studio and allows for a developer to graphically create a UI without the need to understand Apple concepts like an outlet. As Miguel de Icaza says, "Since the beginning of time, man has asked, ‘What in the world is an outlet?'"
- Size Classes: Apple has a set of devices it must support with various sizes and pixel densities. Just from the size standpoint, Apple has devices that are 3.5", 4", 4.7", 5.5", 7.9" and 9.7". Size classes are the general design sizes for Apple devices.
Storyboards
Before getting into anything new with iOS, I'll discuss two important features of iOS that haven't been discussed in the column before -- storyboards and auto layout. Each one is worthy of its own article, but I'll keep this really short.
Storyboards is a mechanism to graphically create a UI including screen transitions. This is a great improvement over creating .xib files with XCode or programmatically creating UIs. From a storyboard, a developer will be able to see the screens, as well as the transitions between screens. This is a great improvement over the previous .xib-based design, which allowed a developer to graphically display only one screen at a time and did not allow a developer to visually see any of the necessary changes between the screens. The first generation of storyboards required that a different storyboard be created for the iPhone and iPad platforms. Now, Apple has released storyboards support that allows for both the iPhone and iPad platforms via the same storyboard file.
Xamarin iOS Designer
The Xamarin iOS Designer is a design surface for both Xamarin Studio on the Mac and Visual Studio on Windows. The designer allows developers to visually design a UI, including the movement between the screens. The designer is built to work with storyboards and is analogous to the designer in XCode. The biggest benefit it has is that it's self-contained to Visual Studio and Xamarin Studio. There's no requirement to interoperate with the XCode design surface. Previously, this integration between XCode and Xamarin Studio was a source of many problems.
I'll walk through a simple example using the iOS Designer that was created with Xamarin Studio 5.5.2.
1. For this example, create an empty Unified API project as shown in Figure 1. You may be wondering what a Unified API project is. With the release of iOS 7, Apple introduced 64-bit CPUs in the iPhone 5s. The Unified API is the Xamarin API that supports 32-bit, as well as 64-bit CPUs in iOS. (Note: The Xamarin Unified API for iOS was being beta tested at the writing of this article.)
2. Within the AppDelegate.cs file you'll need to make some changes. The code shown in Listing 1 will support storyboards. There are a set of event handlers and a property for the window.
Listing 1: AppDelegage.cs Launches the UI, and Listens to App Events from iOS
// The UIApplicationDelegate for the application.
// This class is responsible for launching the UI of the application,
// as well as listening (and optionally responding) to application
// events from iOS.
[Register ("AppDelegate")]
public partial class AppDelegate : UIApplicationDelegate
{
// class-level declarations
public override UIWindow Window {
get;
set;
}
// This method is invoked when the application is about to move from active to inactive state.
// OpenGL applications should use this method to pause.
public override void OnResignActivation (UIApplication application)
{
}
// This method should be used to release shared resources and
// it should store the application state.
// If your application supports background execution,
// this method is called instead of WillTerminate when the user quits.
public override void DidEnterBackground (UIApplication application)
{
}
// This method is called as part of the transition from background to active state.
public override void WillEnterForeground (UIApplication application)
{
}
// This method is called when the application is about to terminate. Save data, if needed.
public override void WillTerminate (UIApplication application)
{
}
}
3. Create a storyboard. In this case, an empty iPhone storyboard is created and is named MainStoryboard.storyboard.
4. Open the properties of the iOS project. In the iOS Application tab, the setting for the Main Interface will need to be set. The dropdown will display the storyboards in the project. In Figure 2, the storyboard that was created in the previous step is selected.
5. Open the storyboard by double-clicking on the storyboard file. This will open the storyboard iOS Designer, as shown in Figure 3. Notice there's a toolbox of controls available to you. Within the toolbox, you can grab and drop controls onto the storyboard design surface.
6. The first step is to add a navigation controller to the storyboard. A UIViewController is added automatically. The UIViewController is set as the root view controller by selecting the navigation controller, holding the Ctrl key, connecting to the UIViewController, and finally defining the UIViewController as the root view controller (see Figure 4).
7. In this example, a button will be added to the existing UIViewController and an additional UIViewController.
8. The question becomes how to programmatically make changes to the presented view controllers. This is done by adding classes for the root view controller class. This will result in creating a designer.cs file, as well as a .cs file. These can be thought of as similar to the codebehind files from ASP.NET Web Forms. The content of the designer file is shown in Listing 2. The content of the .cs file is shown in Listing 3.
Listing 2: Content of RootViewController Designer.cs File
using System;
using Foundation;
using UIKit;
using System.CodeDom.Compiler;
namespace iOS8UI
{
[Register ("RootViewController")]
partial class RootViewController
{
[Action ("TouchMe:")]
[GeneratedCode ("iOS Designer", "1.0")]
partial void TouchMe (UIButton sender);
void ReleaseDesignerOutlets ()
{
}
}
}
Listing 3: Content of RootViewController.cs File
using System;
using Foundation;
using UIKit;
using System.CodeDom.Compiler;
namespace iOS8UI
{
partial class RootViewController : UIViewController
{
public RootViewController (IntPtr handle) : base (handle)
{
}
partial void TouchMe (UIButton sender)
{
Console.WriteLine("Touched Button");
var vc = this.Storyboard.InstantiateViewController("SecondScreenController") as
UIViewController;
this.NavigationController.PushViewController(vc, true);
}
}
}
This example is simple; however, it shows how to navigate between view controllers, as the result of this application is that it will allow a user to navigate between two UIViewControllers. For more examples, check the resources at the end of this article.
There are a number of other features to the designer. These features include zooming in and zooming out to get more detail, adding and removing constraints in auto layouts, and displaying the storyboards in a phone, tablet, and generic container.
Auto Layouts
Many of the samples in this column have discussed laying out UIs programmatically in code. I've written about how to do that in a previous column. Many longtime iOS developers prefer this complete control of the layout with the use of frames and rectangle objects. This also requires that you handle the interrelationships between controls, as well as what happens when a user goes from the landscape view to the profile view and back again. This can be a major exercise in frustration for developers. In fact, some popular applications don't even support any orientation besides portrait (looking at you, Twitter for iPhone).
Getting the calculations correct to handle the orientation changes can be more work than they're worth. To help with this, Apple created a feature called Auto Layout. Auto Layout allows you to create a mathematical relationship between elements. These relationships are defined via a set of constraints between individual elements or set of elements. While constraints can be applied programmatically, they may also be applied in the design surface, as well. To enable constraints in an open storyboard, there's a button that developers need to select in the iOS designer, shown in Figure 5.
How do you create a constraint? It's fairly simple. Once a control is selected, there's a small square that's displayed in the middle of the screen. Selecting the small square and then dragging toward the window side or other point on the screen will create a constraint. This is shown in Figure 6.
Finally, the question will pop up: How do you edit/delete an existing constraint? This is also available within the editor. When a view is selected on the layout option for the editor, the user can edit/delete existing constraints, as shown in Figure 7. Some of the options for constraints include height, width and location on the screen.
Size Classes
As I mentioned, iOS devices come in a number of different size and screen resolutions. Size classes are used to enable a storyboard (or .xib file) to work across multiple screen sizes. Size classes allow you to build an interface that's consistent across the various screen sizes and orientations.
What is a size class? A size class is the relative amount of height and width for a device. Each dimension can be designed as compact, regular or any. The sizes for a view controller are based on the following factors:
- The screen size of the device.
- The orientation of the device.
- The amount of the screen that's available to the view controller. For example, a split view controller displays the master and detail controllers. Neither controller has access to the full screen while the split view controller is displayed on screen.
To enable size classes in a storyboard, simply select a generic layout while in the design surface. This is shown in Figure 8.
To design a screen with size classes, select the size class for which the application should be designed. This is next to the VIEW AS dropdown, as shown in Figure 9.
Wrapping Up
There's a new way to create a UI with Xamarin and take advantage of the new features in iOS 8 with storyboards. Hopefully, I've given you enough to get started with the new set of tools from both Xamarin and Apple to improve the experience in developing UIs.
About the Author
Wallace (Wally) B. McClure has authored books on iPhone programming with Mono/Monotouch, Android programming with Mono for Android, application architecture, ADO.NET, SQL Server and AJAX. He's a Microsoft MVP, an ASPInsider and a partner at Scalable Development Inc. He maintains a blog, and can be followed on Twitter.