iOS 11: Safe Area Layout Guide và Large Titles

Safe Area Layout Guide

Như chúng ta đã biết, Apple lần đầu giới thiệu đến lập trình viên topLayoutGuidebottomLayoutGuide - hai thuộc tính của UIViewController lần đầu trên iOS 7. Chúng cho phép lập trình viên tạo ra các contraints giữ cho nội dung của app không bị che mất bởi một số đối tượng mặc định của UIKit như status bar, navigation bar, tab bar.

Nhìn lại sơ qua về Top và Bottom Layouts Guides

Cùng xem qua một ví dụ về việc sử dụng top và bottom layout guides đối với một view controller nằm trong cả navigation controller và tab bar controller: View màu xanh chứa nội dung sẽ được căn với cạnh dưới của top layout guide và đỉnh của bottom layout guide. Hai thuộc tính top và bottom layout guide sẽ tự động tùy chỉnh độ cao theo mỗi kích cỡ màn hình device khác nhau, và như thế content view cũng sẽ được thay đổi một cách thích hợp.

Điểm mới của Safe Area Layout Guide

Trên iOS 11, hai thuộc tính top và bottom layout guide đã chính thức bị deprecated, và được thay thế bằng một đối tượng duy nhất có tên là safe area layout guide Chúng ta sẽ tạo các contraint ứng với cạnh trên và dưới của đối tượng safe layout guide. Cách này hoàn toàn tương tự như đối với top, bottom layout guide, và chúng ta có thể dễ dàng thay đổi các giá trị width, height, center của safe area.

Migrating Storyboards

Chúng ta có thể convert từ top, bottom layout guide thành safe area layout guide bằng cách thay đổi cài đặt trong phần File Inspector của Storyboard, lặp lại thao tác này lần lần lượt cho từng Storyboard Storyboard sẽ tự động thay đổi top, bottom layout guide bằng safe area và tiến hành cập nhật các contraints.

Tạo contraints bằng code

Chúng ta có thể tạo các contraint bằng code, bằng cách sử dụng thuộc tính safeAreaLayoutGuide của UIView. Chúng ta tạo một reference đến view màu xanh trong ví dụ trên:

private let greenView = UIView()

Chúng ta tạo ra một phương thức để cài đặt các thuộc tính cũng như contraint cho view và gọi đến phương thức này trong viewDidLoad:

private func setupView() {
    greenView.translatesAutoresizingMaskIntoConstraints = false
    greenView.backgroundColor = .green
    view.addSubview(greenView)
    }

Tạo các contraint trái, phải như sau:

 let margins = view.layoutMarginsGuide
    NSLayoutConstraint.activate([
      greenView.leadingAnchor.constraint(equalTo: margins.leadingAnchor),
      greenView.trailingAnchor.constraint(equalTo: margins.trailingAnchor)
      ])

Với iOS thấp hơn iOS 11, chúng ta cần phải tiến hành một bước check xem thuộc tính safe area layout guide có được hỗ trợ không với từ khóa #available, nếu không chúng ta phải sử dụng top, bottom layout guide cho các version iOS thấp hơn:

if #available(iOS 11, *) {
  let guide = view.safeAreaLayoutGuide
  NSLayoutConstraint.activate([
   greenView.topAnchor.constraintEqualToSystemSpacingBelow(guide.topAnchor, multiplier: 1.0),
   guide.bottomAnchor.constraintEqualToSystemSpacingBelow(greenView.bottomAnchor, multiplier: 1.0)
   ])

} else {
   let standardSpacing: CGFloat = 8.0
   NSLayoutConstraint.activate([
   greenView.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: standardSpacing),
   bottomLayoutGuide.topAnchor.constraint(equalTo: greenView.bottomAnchor, constant: standardSpacing)
   ])
}

Lưu ý

Thuộc tính safeAreaLayoutGuide là một property của UIView trong khi topLayoutGuidebottomLayoutGuide là hai thuộc tính của UIViewController. Bản iOS 11 beta cũng có một thuộc tính safeAreaLayoutGuide nằm trong UIViewController nhưng nó đã bị deprecated trên bản chính thức. Phương thức constraintEqualToSystemSpacingBelow là một phương thức mới xuất hiện trên iOS 11, nó tương tự với* less than and greater than*. Còn đối với horizontal spacing thì chúng ta có phương thức constraintEqualToSystemSpacingAfter. Nếu chúng ta có một custom toolbar, chúng ta cần tăng kích thước của safe area với thuộc tính additionalSafeAreaInsets nằm trong UIViewController.

Larger Navigation Bar Titles

iOS 11 đã thêm một thuộc tính vào UINavigationItem, nó cho phép đối tượng Navigation bar có thể lớn hơn và chứa thêm một cái gọi là out-of-line title. Apple đề xuất cho lập trình viên rằng title lớn trên Navigation bar được sử dụng đối với view controller đầu tiên của Navigation controller, nhưng chúng ta có thể dùng nó với bất kì view controller nào.

Để hiển thị tiêu đề lớn cho Navigation bar, chúng ta cài đặt thuộc tính largeTitleDisplayMode về .always:

let vc = UIViewController()
vc.navigationItem.largeTitleDisplayMode = .always

Vâng, chỉ có thế, và bây giờ app của bạn sẽ từ trạng thái giống như sau: trở thành

Bạn có thể thấy, sẽ có lỗi xảy ra đó là nội dung của Top Label đã bị thanh Navigation Bar che mất do Navigation Bar quá lớn, bây giờ là lúc sử dụng Safe Area: Tạo một reference đến đối tượng toplabel và cài đặt contrains cho nó như sau:

topLabel.topAnchor.constraint(
-  equalTo: view.topAnchor,
-  constant: 64
+  equalTo: view.safeAreaLayoutGuide.topAnchor
).isActive = true

Cùng xem thành quả:

Trên đây tôi vừa đề cập đến hai đối tượng mới trên iOS 11 mà Apple giới thiệu, bạn có thể tìm thêm trong sự kiện WWDC 2017 của Apple để biết thêm chi tiết.

Where go from here

Bạn có thể đọc thêm part 2 tại đây Safe Area Layout Guide iOS 11 (Part 2)