12/08/2018, 16:48

Adaptive User Interfaces trong ứng dụng iOS

Apple ngày càng giới thiệu nhiều iPhone, iPad với đủ loại kích thước màn hình khác nhau. Ngoài ra, chúng ta lại có 2 chế độ hiển thị orientation: thẳng đứng (portrait), quay ngang (landscape) và 3 chế độ adaptation cho iPad: full screen, split view 2/3, split view 1/3. Vì vậy tổ hợp các trường hợp ...

Apple ngày càng giới thiệu nhiều iPhone, iPad với đủ loại kích thước màn hình khác nhau. Ngoài ra, chúng ta lại có 2 chế độ hiển thị orientation: thẳng đứng (portrait), quay ngang (landscape) và 3 chế độ adaptation cho iPad: full screen, split view 2/3, split view 1/3. Vì vậy tổ hợp các trường hợp xảy ra của UI lên đến cả trăm, rất phức tạp và khó khăn để có thể hiển thị giao diện tối ưu cho tất cả.

Giả sử chúng ta có 2 design như sau cho 2 chế độ portrait và landscape như sau.

Rõ ràng là rất khó khăn và gần như không thể dùng chỉ mỗi Auto Layout và các contraints để design yêu cầu trên trong một View/View Controller Scene với Interface Builder. Nhiều người sẽ nghĩ ngay đến việc dùng 2 file XIB, một cho design portrait và một cho design landscape. Hoặc 2 view trong một file XIB. Sau đó, khi init view thì sẽ kiểm tra orientation hiện tại là portrait hay lanscape mà load view từ UINib tương ứng. Cách làm này cũng rất ổn, nhưng mỗi khi cần đổi design (ví dụ cần đổi text label, đổi màu button...), chúng ta lại phải đổi 2 lần trên 2 file XIB. Vì vậy, trong bài viết này, chúng ta hãy thử dùng Adaptive User Interfaces để giải quyết bài toán trên theo một cách khác. Adaptive User Interfaces là một khái niệm mới được giới thiệu trong WWDC 2016 với iOS 10 và Xcode 8, cho phép thiết kế giao diện nhiều loại kích thước màn hình, chế độ hiển thị một cách linh động, dễ dàng.

Trước iOS 8, chúng ta thường làm các storyboard riêng cho iPad và iPhone. Thậm chí là sử dụng property orientation của status bar, của device để lựa chọn và init các ViewController/View thích hợp. Cùng với sự phát triển và đa dạng về kích thước màn hình, iOS 8 còn giới thiệu thêm một loại ViewController mới. Đó là SplitViewController với 2 chế độ đa nhiệm slide over và multitasking. Tất cả đã làm cho việc layout cho từng loại kể trên ngày càng trở nên phức tạp. Và để đơn giản hóa mọi thứ, Apple đã đưa ra một khái niệm mới là Size-Classes. Thay vì phải layout cho nhiều loại thiết bị, độ phân giải, chế độ đa nhiệm và orientation, bạn chỉ cần quan tâm, tập trung vào 2 loại awidth: Compact hoặc Regular và 2 loại height: Compact hoặc Regular. Từ hàng trăm tổ hợp nay chỉ cần 4 tổ hợp. Cụ thể được thể hiện trong bảng sau: Ngoài ra:

  • Khi ở chế độ landscape, các iPhone (trừ iPhone loại plus) vẫn được xếp vào loại Compact awidth (wC).
  • Tất cả các loại iPad cho dù ở chế độ portrait hay landscape đều được xếp vào loại Regular awidth, Regular height (wR hR). Chính vì vậy khi chuyển đổi orientation sẽ không trigger đổi size class.

Bạn có thể tìm hiểu về Size-Classes tại trang document của Apple: https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/AutolayoutPG/Size-ClassSpecificLayout.html

Portrait layout

Dùng Xcode 8 trở lên, tạo mới project và trong Main.storeboard, hãy chắc chắn rằng option Use Trait Variations được enable trong View Controller Scene hiện tại. Mặc định khi tạo mới project từ Xcode 8 trở lên, option này sẽ mặc định được enable. Nhưng nếu bạn nâng cấp project từ Xcode cũ lên thì không. Trong View Controller Scene, kéo thả các component, design giao diện portrait như ở trên trước.

Từ Xcode 8 trở đi, Apple đã bổ sung nút View as: iPhoneXXX (wC hR) trên cùng toolbar với nút zoom, và các nút Add constraint. Chúng ta có thể preview UI trên các kích thước màn hình khác nhau cùng orientation mà không cần run app.

Landscape layout

Để cài đặt lại các constraint cho layout landscapt, chuyển sang View as iPhone 8 (wC hC), chế độ Landscape, rồi nhấn nút Vary for Traits để bắt đầu custom constraint cho trait mới. Vì chúng ta đang thiết kế lại cho mode landscape nên chọn Height (Compact).

Click vào từng component trong view, chọn tab Size Inspector, double click vào từng constraint cần thay đổi:

  • Đối với các constraint chỉ xuất hiện trong mode portrait, không cần trong mode landscape, click vào nút (+) cạnh option Installed, chọn Width: Any, Height: Compact, Gamut: Any, click Add Variation. Tích vào option Installed của Variation mới tạo, bỏ tích (uninstall) option Installed đầu tiên. Như vậy, constraint này chỉ được install trong trường hợp device có trait height loại Compact (mode landscape của iPhone).

  • Đối với các constraint chỉ cần thay đổi constant, click vào nút (+) cạnh property Constant, chọn Width: Any, Height: Compact, Gamut: Any, click Add Variation. Nhập constant mới cho constrant. Constant này sẽ chỉ được sử dụng trong mode landscape của iPhone.

Khi đang View as iPhone SE (wC hC) thì các constraint không được install trong trait này sẽ bị mờ đi trong cửa sổ Document Outline. Sau khi chỉnh sửa xong các layout, nhấn nút Done Varying để hoàn tất việc re-constraint.

Cuối cùng chúng ta hoàn thiện được layout mới cho chế độ landscape trên iPhone như sau:

Chạy thử app trên iPhone SE chẳng hạn, xoay dọc màn hình và xoay ngang màn hình, giao diện sẽ thay đổi như yêu cầu ở trên. Chế độ portrait:

Chế độ landscape:

0