Everyone’s excited about the iPhone X, the “iPhone that is entirely screen” — and what a screen! Plus Face ID, TrueDepth selfie/animoji camera, 12-megapixel wide-angle and telephoto rear cameras, A11 Bionic neural engine chip, and wireless charging. But the amazing new screen requires a few changes to your app design. In this tutorial, you’ll explore the new aspect ratio, and build an app with a search controller integrated into the navigation bar. Then you’ll explore how to fix an app that was created shortly before the iPhone X announcement: is it enough to just turn on safe area? Read on to find out.
What’s Different?
First, a quick rundown on what’s different about the iPhone X screen:
- Screen size is 375 x 812 points, so the aspect ratio is 9:19.5 instead of 9:16. That’s 145 pts more than the iPhone 6/7/8’s 4.7″ screen but the status bar uses 44 pts, and the home indicator almost doubles the height of the toolbar.
- Screen resolution is 3x: 1125 x 2436 pixels.
- Screen design must take into account the sensor housing, home indicator and rounded corners.
- In portrait, the navigation bar is 88 pts, or 140 pts for large titles. The toolbar is 83 pts instead of 44 pts. In landscape, the toolbar is 53 pts, and layout margins are 64 pts instead of 20 pts.
- In portrait, the status bar is taller — 44 pts, not 20 pts — and uses space not used by the app, either side of the sensor housing. And it doesn’t change size to indicate phone, location-tracking, and other background tasks.
Geoff Hackworth’s Medium article has super-helpful diagrams of the new screen anatomy, courtesy of his Adaptivity app.
Getting Started
Download the starter package, and unzip it.
First, see for yourself what happens when you load a 9:16 image into an iPhone X screen. Open AspectRatioSample, then open Main.storyboard. Set View as to iPhone X, and select the image view. In the Attributes Inspector, switch Content Mode between Aspect Fit and Aspect Fill:
The 8Plus image were created by stacking two image views, building and running in the iPhone 8 Plus simulator, then taking a screenshot. So the image’s aspect ratio is 9:16.
The image view’s constraints are set to fill the safe area, so its aspect ratio is 9:19.5.
In Aspect Fit, the black view background shows above and below the image (letter-boxing). Aspect Fill covers the view, but crops the sides of the image.
In landscape orientation, Aspect Fit would pillar-box the image (show the background view on the sides), and Aspect Fill would crop the top and bottom.
Assuming you don’t want to create different images just for iPhone X, and you want to cover the view, then you’re going to get cropping.
Designing a New App
Close AspectRatioSample, and open NewCandySearch. Build and run on the iPhone X simulator:
This is a master-detail app with a list of candies. The detail view shows an image of the selected candy.
I’ll wait while you get your favorite snack! ;]
Scroll the table view, to see that it makes no attempt to avoid the home indicator. This is perfectly OK for vertically scrollable views and background images.
- Avoid the sensor housing and home indicator, except for background image and vertically scrollable views.
- Avoid placing controls where the home indicator overlaps, or corners crop.
- Don’t hide or draw attention to sensor housing, corners or home indicator.
Use Auto Layout
Open Main.storyboard, select either view controller, and show the Identity Inspector:
New projects created in Xcode 9 default to using Auto Layout and Safe Area Layout Guides. This is the simplest way to reduce the work needed for iPhone X design.
- Use safe area layout guides.
- Use margin layout guides.
- Center content or inset it symmetrically.
Use Standard UI Elements
Now you’re going to add a search bar with scope bar. And you might as well opt for the new large title, too.
Select Master Scene/Navigation Bar, show the Attributes Inspector, and check the box for Prefers Large Titles:
While you’re here, select the table view’s cell, and set its background color to light gray:
Next, open MasterViewController.swift: it already has most of the search controller code. You just have to replace the TODO
comment in setupSearchController()
with this:
// In iOS 11, integrate search controller into navigation bar
if #available(iOS 11.0, *) {
self.navigationItem.searchController = searchController
// Search bar is always visible
self.navigationItem.hidesSearchBarWhenScrolling = false
} else {
tableView.tableHeaderView = searchController.searchBar
}
If the device is running iOS 11, you set the navigation item’s searchController
property; otherwise, you put the search bar in the table view’s table header view.
Build and run on the iPhone X simulator. Admire the large title, then rotate the simulator to landscape, and tap the search field to show the scope bar:
The search field, cancel button and scope bar are all nicely inset from the rounded corners and sensor housing. The cell background color extends all the way across, and the table view scrolls under the home indicator. You get all these behaviors free, just for using standard UI elements.
Build and run the app on the iPhone 8 simulator, to see that it looks fine there, too:
Here are some other recommendations:
Status Bar
- The iPhone X status bar is higher, so dynamically position content based on the device type, instead of assuming a fixed 20-pt height.
- Always show the status bar unless hiding it adds real value to your app.
3x Screen Resolution
- Use PDF for flat vector artwork; provide @3x and @2x of rasterized artwork.
- An app doesn’t use 3x if it doesn’t have a LaunchScreen.storyboard.
Home Indicator Special Cases
- If your app uses the swipe-up-from-bottom gesture, turn on edge protect with
preferredScreenEdgesDeferringSystemGestures()
: the user must swipe up twice to access the home indicator. - If your app includes passive viewing experiences, turn on auto-hiding with
prefersHomeIndicatorAutoHidden()
: the home indicator fades out if the user hasn’t touched the screen for a few seconds, and reappears when the user touches the screen.
iPhone X Simulator vs Device
- Use the simulator to check portrait and landscape layout.
- Use an iPhone X device to test wide color imagery, Metal, front-facing camera.
Other Stuff
- Don’t reference Touch ID on iPhone X. Don’t reference Face ID on devices that support Touch ID.
- Don’t duplicate system-provided keyboard features like Emoji/Globe and Dictation buttons.
Updating an Existing App
What if you want to update an existing app for iPhone X? First, update its assets, including background images, to PDF or add @3x images. Then make sure it has a LaunchScreen.storyboard, and turn on Safe Area. Safe area layout guides change top, bottom and edge constraints, so check these, and fix them if necessary.
Check for any layout that depends on a 20-pt status bar or 44-pt tool bar, and modify it to allow for different heights. Or, if your app hides the status bar, consider unhiding it for iPhone X.
Next, set View as to iPhone X, and check every layout configuration. Move controls away from the edges, corners, sensor housing and home indicator.
Consider integrating search view controllers into the navigation bar.
Build and run the app on the iPhone X simulator, and check every layout configuration. In landscape, check that table view cell and section header content is inset, but the background extends to the edges.
Here’s a simple example to work through. Download the (original) finished sample app from UISearchController Tutorial. This app was built with Xcode 9 beta, before Apple announced the iPhone X, so Tom Elliott couldn’t test it on the iPhone X simulator.
Build and run it on the iPhone X simulator. In portrait, it looks like NewCandySearch, plus the navigation bar has a candy-green background color and a fancy title image instead of a large title:
But there’s a line between the navigation bar and the search bar, because the search bar is in the table header view. It gets worse: tap in the search field to show the scope bar:
The search bar replaces the navigation bar, removing the background color from the status bar. The search bar is still candy-green, so it just doesn’t look right.
To see more problems, cancel the scope bar, then rotate to landscape:
The title image is slightly clipped, and the sensor housing cuts a bit off the lower left corner of the search bar. But the table view isn’t customized, so its cell contents are well clear of the sensor housing.
Again, tap in the search field to show the scope bar:
Now the rounded corners clip the search bar.
Turning on Safe Area
Open Main.storyboard, select one of the view controllers, and show the File Inspector:
This app doesn’t use safe area layout guides! So check that checkbox, then check the constraints now refer to Safe Area:
Build and run, and see how it looks in landscape, with the scope bar:
It’s even worse! The table header view extends far beyond its superview, although the table footer view is fine. This is possibly another iOS 11 bug, which might be fixed by the time you read this tutorial.
Even if Safe Area prevented the corner clipping, it’s not a good look for the status bar to lose its background color when the search bar replaces the navigation bar. You can fix that by moving the search bar into the navigation bar, so that’s what you’ll do next.
Integrating the Search Bar
Well, this is easy — just copy the NewCandySearch code that sets the navigation bar’s searchController
into CandySearch. Open MasterViewController.swift in both projects, and copy these lines from NewCandySearch:
// replace tableHeaderView assignment with this
if #available(iOS 11.0, *) {
self.navigationItem.searchController = searchController
// Search bar is always visible
self.navigationItem.hidesSearchBarWhenScrolling = false
} else {
tableView.tableHeaderView = searchController.searchBar
}
In MasterViewController.swift of CandySearch, paste these lines in viewDidLoad()
, and comment out this line:
tableView.tableHeaderView = searchController.searchBar
Now open AppDelegate.swift, and find these lines:
UISearchBar.appearance().barTintColor = .candyGreen
UISearchBar.appearance().tintColor = .white
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).tintColor = .candyGreen
Delete or comment out the first line: the search bar will get its tint color from the navigation bar.
Build and run, and tap in the search field to show the scope bar:
So that’s fixed the status bar background color, but now the text field is also green, making it hard to see the search field prompt text and icon. The insertion bar is also green, but you can fix that — change the third appearance
setting in AppDelegate.swift to:
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).tintColor = .white
Below this, add the following line:
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).backgroundColor = .white
This should make the text field background white but, at the time of writing this tutorial, it doesn’t work, which suggests another iOS 11 bug. As an interim fix, you could change the color of the search field prompt text and icons. For example, to make the prompt text white, add the following code to AppDelegate.swift in application(_:didFinishLaunchingWithOptions:)
:
let placeholderAttributes: [NSAttributedStringKey : Any] = [NSAttributedStringKey(rawValue: NSAttributedStringKey.foregroundColor.rawValue): UIColor.white, NSAttributedStringKey(rawValue: NSAttributedStringKey.font.rawValue): UIFont.systemFont(ofSize: UIFont.systemFontSize)]
let attributedPlaceholder: NSAttributedString = NSAttributedString(string: "Search", attributes: placeholderAttributes)
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).attributedPlaceholder = attributedPlaceholder
To make the search icon and clear button white, add the following code to viewDidLoad()
in MasterViewController.swift:
let textField = searchController.searchBar.value(forKey: "searchField") as! UITextField
let glassIconView = textField.leftView as! UIImageView
glassIconView.image = glassIconView.image?.withRenderingMode(.alwaysTemplate)
glassIconView.tintColor = .white
let clearButton = textField.value(forKey: "clearButton") as! UIButton
clearButton.setImage(clearButton.imageView?.image?.withRenderingMode(.alwaysTemplate), for: .normal)
clearButton.tintColor = .white
Again, this doesn’t work at the time of writing this tutorial, but it might be fixed by the time you read this.
Where To Go From Here?
You now have a good idea of how to design apps that look great on the iPhone X, as well as the other iPhones. Here is a bundle of the two sample projects, with all the code from this tutorial. If you want to dig deeper, check out these resources:
Apple
- Designing for iPhone X: Mike Stern presents the iPhone X Human Interface Guidelines
- Building Apps for iPhone X: Paul Marcos updates the WWDC app, fixing three issues by using safe area layout, setting background color for background view instead of content view, and moving search bars into the navigation bar.
- iPhone X Design Resources: Templates for Photoshop, Sketch and Adobe XD.
raywenderlich.com
If you’re new to auto layout, or just need to brush up, check out our tutorial and video course:
- Auto Layout Tutorial in iOS 11: Getting Started: Updated to iOS 11, Xcode 9 and Swift 4, but pre-iPhone X-announcement.
- Beginning Auto Layout video course: At the time of writing this tutorial, this video course was up-to-date for iOS 10, Xcode 8 and Swift 3.
- Adaptive Layout Tutorial in iOS 11: Getting Started: Updated to iOS 11, Xcode 9 and Swift 4, but pre-iPhone X-announcement. Create a single layout that works on all iOS devices, without platform-specific code. Adaptive layout will also look good on future devices that haven’t even been released yet.
I hope you’ll soon have your apps running beautifully on the iPhone X. If you have any questions or comments, please join the forum discussion below!
The post Development Tutorial for iPhone X appeared first on Ray Wenderlich.