Cross Platform
Android
iOS
Mac

iPad + Universal (iPhone + iPad) Apps

Building Xamarin.iOS Applications that run on both the iPad and iPhone

This is final tutorial in the Getting Started with Xamarin.iOS series. It walks through creating an iPad application, and then examines how universal applications can be created that are designed to work with both the iPad and the iPhone. Next, it walks through creating a universal application using the Universal Application Project Template, and finally, it introduces a customization to the template that allows more complex applications to be targeted to both devices.

Overview

We’ve covered a lot of ground so far in these Getting Started tutorials. So far, we’ve introduced the toolset, building and deploying applications, Outlets and Actions, and the MVC pattern. However, everything that we’ve done has all been iPhone/iPod Touch based. In this final tutorial in the Getting Started series, we’re going to walk through creating an iPad application, then, we’re going to walk through creating a universal application that runs equally well on both the iPhone and the iPad

The following are screenshots of one of the first universal application we’re going to build:

Requirements

This tutorial builds on the concepts introduced in the previous Getting Started tutorials. Therefore, it’s highly recommended that you complete Getting Started tutorials 1-4 before beginning this one.

Building for iPad

From an application perspective, building for the iPad is nearly the same process as building for the iPhone. Everything that we’ve learned thus far in these tutorials applies to iPad applications. The MVC Pattern still applies, and although there are a couple of additional iPad-only controls, the rest of the UIKit still applies, too.

The main difference between iPhone applications and iPad applications is in designing the UI, because the iPad presents a much larger form factor; it’s nearly the size of a common sheet of paper.

Having this much screen real estate means that functionality that might be split across several screens in the iPhone can fit on a single screen in the iPad. For instance, let’s look at the Settings Application in the iPhone:

The same functionality is collapsed into fewer screens in the iPad:

In fact, with all that screen space, you could easily imagine how the Settings Application could be collapsed further.

This is the reason that there are additional controls for the iPad. In the above screenshot, the Settings Application uses the split view controller, which is only available on the iPad.

OK, let’s take a look at actually creating an iPad application.

Creating our iPad Application

Open up Xamarin Studio (formerly MonoDevelop) and create a new solution. In the New Solution dialog, select C# : iOS : iPad. You’ll notice that all the iPhone templates also have a corresponding iPad template:

We’re going to make a very simple application, so choose Single View Application – iPad and name it Hello_iPad.

In Visual Studio, select Visual C# : iOS : iPad, and select HelloWorld Application.

The resulting project looks nearly identical to the Hello, iPhone application we created in an earlier Getting Started tutorial:

Project Options

In fact, the only real difference is in our .plist file.

In Xamarin Studio: right-click on the project, and choose Options, we’ll see that the Devices setting is set to iPad:

In Visual Studio: go to the project Properties, and then navigate to the iOS Application pane to see the info.plist file in the basic plist editor. Note how the Devices setting is set to iPad:

By changing Devices setting to iPad, the dialogue also gives options specific to the device.

In the next section, we'll discuss how to design our application's interface with the XCode Interface Builder. XIB integration is currently not supported in Xamarin.iOS for Visual Studio. You will want to move over to your Mac host to work with Interface Builder. Or you can skip this part - the Hello World project template already contains most of the UI code we will be generating.

Interface Builder and iPad Views (in Xamarin Studio)

Editing iPad .xib files in Interface Builder (IB), is exactly like editing iPhone .xib files, except the designer is much larger. Double-click on the Hello_iPadViewController.xib and it’ll open up in IB:

Let’s add a label to the view, and save it:

We don’t need any Outlets or Actions, but adding them is the same process as it is for the iPhone—you open the Assistant Editor, and Control-drag from the control to the .h file.

Running an iPad App

Now let’s build and run our iPad app. Close Interface Builder and return to Xamarin Studio, then choose a Run option from the Start menu to start your iPad app.

In the top left corner of Xamarin Studio, select Debug in the first menu, and iPad Simulator {VERSION} in the second, then click the Run button.

In Visual Studio, you will select the iPhone Simulator option. The application will know to launch the iPad simulator because we've as per our info.plist settings. Then hit the Start button to launch the simulator.

The iOS Simulator will open up and simulate the iPad, which looks nearly the same as the iPhone Simulator, except for the size:

That’s it! We’ve built our first Xamarin.iOS iPad application!

iPad Icons

iPad application icons are specified in the Info.plist file, just like iPhone application icons are. The only difference is the size needed for them. The following table lists the icons and sizes needed for iPad applications:

Icon Use Size for iPad (in pixels)
Application Icon 72x72
Spotlight and Settings

Spotlight: 50x50

Settings: 29x29

App Store Icon (only needed if publshing on App Store) 512x512

To add these icons, follow the same procedure we did for the Hello, iPhone application: right-click on the project and choose Add : Add Files.

To configure these icons, either double-click on the Info.plist file in the Project Navigator, or double-click on the project and choose iPhone Application in the Options dialog.

iPad Default Loading Screens

Specifying a loading screen in iPad is conceptually the same as with iPhone apps, you just move your properly named and sized images into the project root, and iOS will automatically show them during application launch. However, things are slightly more complicated in iPad apps because instead of two images (as there are for the iPhone), you can optionally specify up to four; one for each orientation.

Additionally, unlike the iPhone, the status bar is viewable when an iPad application launches, which means that you must take into account that 20 pixels at the top of the screen are already occupied. This is also dependent on orientation, because the status bar is always at the top. So, if the iPad is in portrait mode, the loading image needs to be 768x1004 pixels, and if in landscape, it needs to be 1024x748 pixels.

The following table lists the types of iPad loading images, as well as their sizes (width x height) and orientations. The images are listed in order of precedence; images further down the list take precedent over images higher in the list:

File Name Size (in pixels) Use
Default~ipad.png 768x1004 This is the basic loading image that is used if a more specific image is not available. If no more specific images are supplied, this should be present.
Default-Portrait~ipad.png 768x1004 This is the generic portrait loading image. This image is used for right-side up (home button on bottom) portrait orientations and takes precedence over Default~ipad.png. Therefore, if you supply this image, Default~ipad.png is not used. Additionally, if Default-PortraitUpsideDown~ipad.png is not supplied, this image is used.
Default-Landscape~ipad.png 1024x748 This is the generic landscape loading image. This image takes precedence over Default~ipad.png. Therefore, if you supply this image, Default~ipad.png is not used. Additionally, if Default-LandscapeLeft~ipad.png or Default-LandscapeRight~ipad.png is not supplied, this image is used.
Default-PortraitUpsideDown~ipad.png 768x1004 This is the portrait upside-down (home button on top) loading image.
Default-LandscapeLeft~ipad.png 1024x748 This is the landscape left (home button on left) loading image.
Default-LandscapeRight~ipad.png 1024x748 This is the landscape-right (home button on right) loading image.

Unless you want to have different images for each orientation, you only need to supply a Default~ipad.png image if your application only supports portrait mode. If your app only supports landscape orientation, you only need the Default-Landscape~ipad.png image. If you support both landscape and portrait orientation, then you should supply at least these two images. This significantly reduces the amount of images you must create, since supplying one for every orientation is typically overkill.

For more information about loading images, see the Apple documentation on Custom Icon and Image Creation Guidelines.

OK, now that we’ve covered iPad applications, let’s take a look at how to build apps that target both the iPhone and iPad.

Universal Applications

Universal iOS applications are applications that will load the appropriate UI, depending on which device they run on. For instance, you might have one UI defined for the iPhone, and another UI defined for the iPad. A universal application will automatically load the correct UI.

This is typically accomplished when the FinishedLaunching method of your application delegate detects which device is running, and then launches the appropriate UI.

Fortunately for us, Xamarin Studio ships with a universal project template that contains the basic code to accomplish this. Let’s take a look at it.

Universal Project Template

Let’s create a new solution, this time we’ll choose C# : iOS : Universal : Single View Application – Universal:

Let’s create a new solution, this time we’ll choose Visual C# : iOS : Universal : HelloWorld Application:

Let’s name the project Hello,_Universal.

If you take a look at the project structure created from this template, you’ll notice something a little different. There is one view controller, but - for those of you using Xamarin Studio - two associated .xib files:

Programmatic Device Detection

To understand how this works, let’s take a look at the code that was generated for Hello_UniversalViewController:

public partial class Hello_UniversalViewController : UIViewController
{
    static bool UserInterfaceIdiomIsPhone {
        get { return UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone; }
    }

    public Hello_UniversalViewController ()
        : base (UserInterfaceIdiomIsPhone ? "Hello_UniversalViewController_iPhone" : "Hello_UniversalViewController_iPad", null)
    {
    }
}

The magic here begins with this line:

get { return UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone; }

The UIDevice.CurrentDevice object exposes a property called UserInterfaceIdiom that returns a UIUserInterfaceIdiom enumeration that lets us know what the current device is. There are two possible values for this enumeration: Pad and Phone, corresponding to the iPad and iPhone/iPod Touch, respectively.

Once we’ve determined which device is running the application, then we base the name of the appropriate .xib file to the base controller:

public Hello_UniversalViewController ()
        : base (UserInterfaceIdiomIsPhone ? "Hello_UniversalViewController_iPhone" : "Hello_UniversalViewController_iPad", null)
    {
    }

This works, because one of the constructors for UIViewController is the following:

public UIViewController (string nibName, NSBundle bundle) : base (NSObjectFlag.Empty))

The base class takes the name of a .xib file based to be used for the view (recall from Getting Started tutorial 3 that Nib is another name for .xib files). In this case, we’re passing either Hello_UniversalViewController_iPhone, or Hello_UniversalViewController_iPad, depending on the device.

Creating the User Interface (for Xamarin Studio)

So far, so good, but let’s actually put this in action. First, let’s open the Hello_UniversalViewController_iPad.xib file in Xcode and add a couple of labels and a button:

We’re going to update the bottom label with some text when the button is clicked, so make sure it’s fairly wide, so that the text doesn’t get truncated.

Next, we’ll do the same thing with the Hello_UniversalViewController_iPhone.xib file:

Again, be sure to make the bottom label fairly wide so the text doesn’t get truncated.

Sharing Outlets and Actions Across Multiple Views (in Xamarin Studio)

So now we have two views that share the same controller, but how do we create Outlets and Actions that work across the two views? Well, it turns out that this is very similar to how Actions are shared.

Let’s first create our Outlets. Open up the iPhone view and the corresponding shared controller .h file in Xcode and Control-drag to create the following outlets:

  • btnClickMe
  • lblOutput

The btnClickMe outlet should be wired to the button, and the lblOutput should be wired to the lower label. When we’re done we should have something like this:

Our .h file should have the following Outlet code:

@property (nonatomic, retain) IBOutlet UIButton *btnClickMe;
@property (nonatomic, retain) IBOutlet UILabel *lblOutput;

Next, let’s open up the iPad view. This time, we’re going to Control-drag to the existing Outlets that we created when the iPhone view was open:

Now our Outlets are shared across the two .xib files. Let’s save our work and switch back over to Xamarin Studio. We can now use the same Outlets in the same ways, whether the app is running on an iPhone or an iPad. Let’s modify our Hello_UniversalViewController class’s ViewDidLoad method to see this in action:

public override void ViewDidLoad ()
{
    base.ViewDidLoad ();
    this.btnClickMe.TouchUpInside += (sender, e) => {
        this.lblOutput.Text = "Clicked @ " +
            DateTime.Now.ToShortTimeString();
    };
}

Now, when we run it and click the button, we should see something like this:

Notice that the iPhone simulator launches by default. We can force the application to run in the iPad simulator by selecting iPad Simulator 4.3 from the Project > iPhone Simulator Target menu. When we run the application now, it will launch in the iPad simulator, and when we click the button, the code will run just as it did when we used the iPhone simulator:

Complex Universal Applications

The approach we’ve used so far, where a single controller manages two different views based on the device, works fine for simple screens in which there are the same Outlets, Actions and user interactions between the iPhone screen and the iPad screen, but this is a rare occurrence in the real world. Typically, iPad apps and iPhone apps differ substantially in terms of UI and user interaction (referred to as User eXperience [UX] when taken together).

For example, consider the following two different interfaces for the same app on different devices:

In this case, we’d want to have two different controllers because the Outlets would be different. This is obviously a contrived UI, but you can imagine that in some applications the UI is drastically different between devices.

To load a different controller depending on the device, the first thing that we should do is to declare a generic UIViewController in our AppDelegate class, rather than a specific one (say homeScreen_iPad or homeScreen_iPhone):

public partial class AppDelegate : UIApplicationDelegate
{
    // class-level declarations
    UIWindow window;
    UIViewController homeScreen;
    …
}

Then, in the FinishedLaunching method, when we determine which device is in use, we load the appropriate controller, and then set that controller as our root:

if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone) {
    homeScreen = new Screens.HomeScreen_iPhone();
} else {
    homeScreen = new Screens.HomeScreen_iPad();
}
window.RootViewController = homeScreen;

Now, when we run the application, the correct controller for the device will be shown.

Summary

Congratulations, this was the final tutorial in the Getting Started series! In this tutorial we learned how to create an iPad-only application, as well as two different approaches to creating universal applications. If you’ve been going through these tutorials from start to finish, you’re now well on your way to becoming a proficient Xamarin.iOS developer!