Mallow's Blog

Designing factors for iPhone X and UI Changes in iOS 11

In iOS, we have the topLayoutGuide and bottomLayoutGuide as properties of UIViewController. These properties are used to create constraints that allow us to keep the content away from UIKit bars like the status bar, navigation or tab bar. These layout guides are deprecated in iOS 11 and it is replaced by a safe area layout guide.

Apple told us in WWDC 2017 Session 412 that Storyboards using safe areas are backwards compatible. This allows the developers to use safe area layout guide starting from iOS 9.  There may be a situation where the developers need to handle constraints in code. In that case, you can use view’s safeAreaInsets property to get the values of the safe area.

iPhone X screen

But remember to use the view’s safe area inset property in the viewDidLayoutSubviews method because we get the correct values only after the view has been completely initialized.

For eg:- When I tried to print the values of safeAreaInset in viewDidLoad method, I got the values as UIEdgeInsets(0, 0, 0, 0).  Again I tried to print the same in viewDidLayoutSubViews method, I got the value as UIEdgeInsets(0, 140, 0, 30), where 140 is the top inset and 30 is the bottom inset in an iPhone X in portrait mode.

iOS 11 Changes

Large tiles

One of the important change is the new large titles in navigation bars. The title gets smaller when you scroll down, in a fashion similar to iOS 10 style where it sits neatly inside the navigation bar itself. If you scroll up, you’ll see the new large title gets a bit larger.This property can be set using

navigationController?.navigationBar.prefersLargeTitles = true

You have the option to control which view controllers should have large titles and which should have small. Apple prefers to use the large tiles only on the first view controller in the navigation stack similar to the setting app. But by default, if you set the preferred large tiles to true, the subsequent view controller in the navigation stack would have the larger tiles. This can be controlled using the property

navigationItem.largeTitleDisplayMode = .never

Text Wrapping in iOS X

Search controllers inside the navigation

Previously you needed to create your UISearchController then add it to your view manually, and most often it is set as their table header view. With iOS 11 you can move it up into the navigation bar, and even have it fixed in place if you want. You can attach search controllers to the navigation bar to have them participate in this shrinking effect similar to the default settings app. If you prefer you can have your search bar to remain static even during scrolling similar to the default Files app. These are handled as follows

navigationItem.searchController = UISearchController(searchResultsController: nil)

navigationItem.hidesSearchBarWhenScrolling = false
Text wrapping with search bar

Deferred gestures

Before iOS 11 the way you tell the system not to grab gestures at the bottom and top edge of the screen are to hide the status bar. Apple has changed the way they handle gestures at the screen edges in iOS 11. From now,  deferring the system gestures has no dependency on the status bar.  They have introduced a method which we can override and inform the system to handle deferred gestures. For eg:- we can use the below method to inform the system to defer the gestures on all edges of the screen.

override func preferredScreenEdgesDeferringSystemGestures() -> UIRectEdge {
       return .all
}

text wrap with dropdown notif

New leading and trailing swipe gestures

One of the new APIs in iOS 11 allows the addition of swipe actions on UITableView rows via the new UISwipeActionsConfiguration class and associated UITableViewDelegate methods. For eg:- look at the below method

func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
         let read = UIContextualAction(style: .normal, title: "Mark as read") { action, view, completionHandler in
print("Marking as read!")
completionHandler(true)
}
read.backgroundColor = UIColor.orange
read.image = UIImage(“read_image”)
let unread = UIContextualAction(style: .normal, title: "Mark as unread") { action, view, completionHandler in
print("Marking as unread!")
completionHandler(true)
}
unread.backgroundColor = UIColor.purple

let config = UISwipeActionsConfiguration(actions: [read, unread])
config.performsFirstActionWithFullSwipe = false
return config
}

REad and unread of text

In the above method, we have created two swipeable actions read and unRead. There is an option to set the title and background colour as expected. You also have the option to set an image, but in the latter case, the title will not be displayed.

Similarly, we have trailing swipe gesture method to handle swipe from the right of table view cell.

func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
      let delete = UIContextualAction(style: .destructive, title: "Delete") { action, view, completionHandler in
           print("Deleting!")
completionHandler(true)
}
      let config = UISwipeActionsConfiguration(actions: [delete])
      config.performsFirstActionWithFullSwipe = true
      return config
}

We can specify the UIContextualAction’s style as normal or destructive. In the latter case, on its action, the cell would be deleted by the system itself. So you have to make sure you call the completion handler after the data has been successfully deleted from the data source.

You also have the option to configure full swipe using config.performsFirstActionWithFullSwipe property as shown in above method.

text with delete option

 

Thus in this post, we have seen the points to consider before designing for iPhone X. Along with it, we have seen the major changes that were introduced in iOS 11 with some sample codes.


Rajtharan G,
iOS Team,
Mallow Technologies

 

Leave a Reply

%d bloggers like this: