PhoneGap Build 7.0.1 supports iOS Launch Storyboards (YAY!)

Example of a iOS Launch Storyboard for iOS. (Credits: https://github.com/kerrishotts/lsb-example-complex#credits)

With the release of PhoneGap Build 7.0.1 on August 1st, 2017, we can now use iOS Launch Storyboards with PhoneGap Build. This means we can use them across Cordova, PhoneGap, and PhoneGap Build, which brings full parity to each tool. Yay! This has a few consequences:

  • PhoneGap Build can now target iPad Pro 10.5" and 12.9" form factors using each device’s native resolution. Apple provided no other supported method for targeting the native resolution on these devices except by using storyboards.
  • PhoneGap Build can now target any new screen form factor in the future (iPhone 8, *cough, cough*), as long as Apple continues to use the same size classes (see below).
  • PhoneGap Build apps can now support split-screen and slide-over multitasking with additional configuration / plugins.
  • Coolest of all: you can target all device form factors and viewports with a single image (if you so desire).

What is a Launch Storyboard?

Apple has long been trying to get developers to build apps that are responsive to viewport size. As a hybrid developer, this sounds an awful lot like “responsive design”. In the early days of iOS development, though, developers would code to a specific viewport size — which worked, since there was only one… until it didn’t work, since there were many.

For a long time, the only way to display a splash was a “launch image” — a PNG file of a specific resolution. Apple has also long been trying to advance the idea that a launch image should reflect the app in an unpopulated state. The idea is that this gives the impression of a faster launch.* The downside, however, has been that developers had to create a separate version of the launch image for each possible viewport. In the beginning, no big deal, but now?

* Personally? I think it makes launches feel slower. But this is just me.

As Apple released devices with new screen sizes, they also took to using those launch images as an indicator of which viewports the app supported. If the app didn’t provide an appropriately-sized launch image, the app would be scaled or letter-boxed instead.

And then the iPad Pro 12.9" was released, and Apple provided no supported method for generating an iPad Pro 12.9" launch image. They also released split- and slide-over multitasking, and no method for generating launch images for all the widely varied viewports that could occur. The only supported method was to use a feature introduced back in Xcode 6: launch storyboards.

If you’re familiar at all with storyboards in Xcode, then a launch storyboard is just a storyboard assigned to display when the app starts. If you’re not familiar with storyboards, the simple explanation is this: a storyboard is a collection of visual designs for the app’s user interface, along with connections (segues) between designs.

Storyboards were now the preferred method of providing launch images. And it made sense — if your app’s launch image should represent an unpopulated UI, then you could (potentially) get away with reusing your existing storyboard as the launch image, and be done with it. Storyboards also have methods for adjusting layout based on size classes, so they can be made to be responsive to viewport sizes.

Launch storyboards are pretty neat — if you’re building a native app and working in Xcode. For hybrid developers who are doing neither, having to launch Xcode, build a storyboard, configure it to be the launch image, etc. was a pain in the rear. And then let’s not forget that technically the Xcode project was treated as a build artifact, and was easily be overwritten, requiring the process to be repeated. Not ideal.

As such, a simple implementation of launch storyboards were incorporated into cordova-ios as of version 4.3.1. Every project now comes with a simple storyboard that contains an image that will scale to fill the screen (respecting aspect ratio). Assuming images with certain filenames are provided in config.xml, Cordova will then configure the app to use the launch storyboard automatically.

The launch storyboard (the image itself is coming from the project — without an image, the storyboard shows as blank; credits: https://github.com/kerrishotts/lsb-example-simple#credits)

Using images in this way isn’t as flexible as building a storyboard from scratch and duplicating the user interface. But, short of building a DSL, using an image seemed the best way. That does have some consequences for how you design a launch storyboard image in Cordova, though, which we’ll get to in a moment.

Using iOS Launch Storyboards

To help you get started, I’ve created five repositories that work with PhoneGap Build. Each one shows a different facet of launch storyboard design, from simple splashes to fine-tuned splashes. You can create a PhoneGap Build app with any of these repos, supply your development key, and you should have an IPA file ready to install on your device. Links to simulations are also supplied below.

Creating your Launch Storyboard

So, how do you create your own launch storyboard? Well, it’s pretty easy if you want to create something simple. It gets a bit more involved if you want to build anything complex.

Before we go any further, though, one thing you should forget: there’s no simple way to easily present an unpopulated UI, like Apple suggests. Images provided will be scaled and cropped from the center, which means it will be next to impossible to make something that looks right on all targeted devices.

You should go check out the documentation on this subject for the full details, but here’s the really short version:

  • Pick a color that matches the background color of your app. Then create a square PNG (2732 x 2732, but any size will technically do). Then fill it. Do a happy dance. (In case you’re wondering: yes, Apple does seem to accept “blank” launch screens. I’ve not had a problem with that approach yet.)

Oh, you didn’t want a blank launch screen? That’s OK — here’s the slightly longer version:

  • Start with a square (at least 2732 x 2732). Granted, no device screens are square, but the launch storyboard will be targeting widely varied viewports anyway. Using a square lets you easily support portrait & landscape orientations in a single image.
  • Design for the center. Because the launch storyboard will rarely match any device screen exactly, it will almost certainly be scaled and cropped. Only information in the center of the launch storyboard is guaranteed to be preserved.
  • Keep it narrow, unless you want to provide variations. iPad multitasking splits can get pretty narrow, which means that a logo that works everywhere else might end up getting cropped when being used with multitasking.
  • Provide variations only when necessary, and only to preserve important information. Logos and text fall into this category. Artwork, generally, does not. Remember, Apple doesn’t suggest getting overly artsy with your launch screens anyway. So, take the easy way out: don’t!
  • Test, test, and test some more. You need to test your launch storyboard on all possible form factors and viewport scales in order to be sure that the launch image isn’t cropped in unfortunate ways (like part of the logo being cut off). Want to take the easy way out? Use my Launch Storyboard Preview Utility. There are some more examples there, too.

Now, how do we get PhoneGap Build to recognize your new launch storyboard image(s)?

First, use the new 7.0.1 CLI by adding the following to your config.xml:

<preference name='phonegap-version' value='cli-7.0.1' />

Second, make sure you’re using cordova-ios@4.4.0 or later, again in your config.xml, or you can just use cordova-ios@latest if you don’t want to pin the project to a specific version (just be careful with that!)

<engine name="ios" spec="latest" />

Third, remove any legacy launch images from your project and config.xml. If you include them, they’ll still be bundled with your project, which means that your app will be larger than it needs to be.

Finally, add in references to your new launch storyboard images, like so:

<splash src="res/screen/ios/Default@2x~universal~anyany.png" /><splash src="res/screen/ios/Default@2x~universal~comany.png" />
...

There’s a few things to note about the format of these tags:

  • There is no width or height attribute. You must not provide either. (If you do, you’ll trigger the legacy launch image processing.)
  • There is a scale specifier in the filename — this can be @1x, @2x, or @3x. It must be provided in order for the storyboard image to be recognized.
  • There is an idiom specifier — this can be universal, ipad, or iphone. Typically you’ll use universal. It must be provided in order for the storyboard image to be recognized.
  • There is a size class specifier — this can be anyany, anycom, comany, or comcom. See the documentation for more on this particular value. If you’re just creating a single launch storyboard, anyany will do. This must also be provided in order for the storyboard image to be recognized.

Otherwise, the name of the file can be anything you like. (No, that’s not limiting at all, is it?) If you’re having problems getting a storyboard image to be recognized, double check the naming scheme.

In general, if you’re creating a single image for all devices, you can get by with just adding a single line to your config.xml:

<splash src="res/screen/ios/Default@2x~universal~anyany.png" />

Quirks you need to be aware of

I’ve seen a few quirks regarding how launch storyboards are supported by iOS:

  • Launch Storyboards are cached. If you don’t see the launch image you expect, try rebooting. If that fails, delete the app and reinstall.
  • If, after installing your app, your device shows a black screen when launching the app, try rebooting. That’s always worked for me. As to why, I’m not sure. It could just be my device, or it could be something else (haven’t pinned it down).
  • If you supply a variation (anycom, comany, comcom), you must also supply the anyany version for the same idiom and scale. Otherwise the variation won’t be used.

Questions? Issues?

If you have any questions, please, don’t hesitate to reach out at any of the following: