Введення в Size Classes у Xcode 6

Привіт всім! Сьогодні хотілося б зробити невеликий вступ у таку штуку, як Size Classes. Вона з'явилася нещодавно разом із Xcode 6, документації по ній від самої Apple зовсім небагато.

Отже, навіщо призначена Size Classes? Всі ми знаємо, що на підході вже iPhone 6 двома (як мінімум) різними розмірами дисплея (4,7 і 5,5), після чого розробникам ще більше доведеться морочитися з версткою UI для них + само собою розширення iPad. У результаті кількість всіх екранів, що підтримуються, буде близько 7 (маленький привіт Android). Герой сьогоднішнього дня — Size Classes — якраз і призначений для того, щоб допомогти вирішити цю проблему. Створимо тестовий приклад у Xcode 6. Виберемо SingleViewApplication, у пункті Devices ставимо Universal:

Height

Далі вибираємо наш Main.storyboard і у вкладці File Inspector ставимо галочку навпроти Use Size Classes (якщо вона не обрана за замовчуванням):

Height

Тепер звернемо увагу на наш storyboard, він не зовсім такий, яким ми звикли його бачити:

Height

Після того, як був обраний Use Size Classes, ViewController прийняв якийсь абстрактний (базовий) розмір, з позначенням wAny hAny (будь-яка висота, будь-яка ширина) про яку поговоримо трохи далі.

Трохи теорії. Кожен створений ViewController має свій UITraitCollection об'єкт (що надає докладну інформацію про характеристики ViewController, доступний з iOS 8, докладніше можна почитати тут), який у свою чергу має 2 Size Class: горизонтальний та вертикальний. Кожен Size Class може мати 3 можливі значення: компактний (compact), звичайний (regular) та будь-який (any). Ці значення змінюються залежно від пристрою та його орієнтації. Тобто додаток буде мати свій окремий інтерфейс для кожногоViewController базуючись на поточному Size Class.

Повертаючись до нашого wAny hAny, що це? Це не що інше як сітка вибору конфігурації для роботи з певним типом пристрою, яка виглядає наступним чином:

classes

При наведенні курсору на сітку Apple підказує розробнику при яких розмірах які пристрої маються на увазі. Загальна картина сітки виглядає так:

Базові значення (any Width any Height):

Height

iPhone ландшафтний режим (compact Width compact Height):

Height

iPhone портретний режим (compact Width regular Height):

Size

iPad ландшафтний та портретний режим (regular Width regular Height):

введення

Потрібно звернути увагу на зелені крапки посередині кожного квадрата сітки. Вони показують, до яких пристроїв будуть застосовані зміни, які ви робите в цій конфігурації. Наприклад, при базових значеннях (any Width any Height) точки показують розробнику, що зміни будуть застосовуватися до всіх типів пристроїв. Тому Apple, рекомендує робити більшу частину роботи з інтерфейсом саме в цій конфігурації.

Повернімося до нашого тестового прикладу. Як було сказано вище зараз, у нашого ViewController базовий Size Class (any Width any Height). Додамо на наш ViewController 3 простих View розміром 100 на 100, пофарбувавши їх у зелений колір, також додамо UILabel та UIButton шириною 600 і висотою 50 також пофарбувавши їх для наочності:

xcode

Додамо Constraints: кнопці - центрування по вертикалі та горизонталі, а також Height та Wight. трьома View - Height і Wight, Horizontal space і Vertical Space. Теж саме зробимо і з UILabel.

У результаті наш ViewController разом із Constraints буде мати такий вигляд:

введення

Запустимо наш додаток на виконання на iPhone 5 portrait та landscape:

Size
classes

та iPad 2:

Size

Як бачимо результат не дуже втішний, на iPhone 5 portrait дві в'ю вилізли незрозуміло куди, в landscape режимі з розмірами в'юх і лейбла просто біда, а їх ширина занадто велика. У iPad все не так страшно, але відстань між лейблом та кнопкою надто велика, а перша UIView розтягнулася.

Спершу виправимо все для iPhone 5. Для початку в Size Classes виберемо (compact Width regular Height) для портретної орієнтації:

Height

Зверніть увагу, що смужка вибору Size Classes стала синьою. Це говорить про те, що ви були уважнішими, оскільки на даний момент знаходитесь не в базовій конфігурації, і зміни 4х типів будуть застосовні тільки до даного типу і орієнтації пристрою. Які ж це зміни? Як було сказано, їх 4:

1) значення Constraint'ів 2) шрифти 3) увімкнення/вимкнення Constraint'ів 4) увімкнення/вимикання subviews

P.S. Нагадаємо, все, що буде далі зроблено, застосовується ТІЛЬКИ до портретної орієнтації iPhone 5, про що нас інформує зелена крапка в сітці Size Classes!

Почнемо з 1 пункту і виправимо значення Constraint, щоб усе виглядало коректно. У цій конфігурації бачимо помилки Constraint:

xcode

Для їх виправлення в даній орієнтації йдемо до налаштувань Constraint, і виберемо значення горизонтальної відстані між View тому що для iPhone воно занадто велике:

введення

У панелі Utilities у вкладці Size Inspector біля пункту Constant (а також біля „Installed“, але про нього пізніше) тиснемо невеликий знак „+“:

Size

І вибираємо „Compact Width Regular Height (current)“:

xcode

Бачимо, що у нас з'явилася нова Constant (wChR), для даної орієнтації, введемо значення 34. Теж саме проробляємо з другим Constraint між 2 і 3 в'ю.

Height

Після чого у нас повинні зникнути помилки пов'язані з відстанню по ширині між в'ю:

xcode

Теж саме зробимо і з шириною кнопки та лейбла для даної орієнтації. Виберемо їх ширину, додамо Constant „Compact Width Regular Height (current)“, та встановимо значення 200:

xcode

Отже, для того щоб „вимкнути“ Constraint, яка нам заважає, потрібно її вибрати зі списку:

xcode

І знову звернутися до вкладки Size Inspector, тільки тепер натискаємо „+“ який біля чекбоксу „Installed“:

classes

Знову ж таки вибираємо і вибираємо "Compact Width Regular Height (current)", і тепер у нас як і з Constant (wC hR) з'явився чекбокс wC hR "Installed", прибираємо його і бачимо, що помилки зникли, а для цієї конфігурації даний Constrain вимкнено:

Size

Запустимо наш додаток на виконання і побачимо, що все відображається коректно (ну майже всі, тому що розміри View не підганяли для конкретного пристрою Xcode автоматично зменшує одну з них):

Height

Цю проблему ми виправимо пізніше.

Виконуємо аналогічні дії для iPhone 5 landscape, виберемо в сітці Size Classes (compact Width compact Height):

Size

Нам потрібно так як і для портретного режиму змінити відстань між в'ю та розміри кнопки та лейбла, я вибрав такі ж значення як і для портретного режиму: відстань між в'ю 34, розмір кнопки та лейбла 200. Запустимо наш апп:

Size

Знову ж таки через те, що ми не підганяли розмір, Xcode розтягує View. Виправимо цю помилку в портретній (compact Width regular Height) та ландшафтній (compact Width compact Height) орієнтації.Виділимо наші 3 завірюхи та вибираємо в меню Editor -> Pin -> Widths Equally. Після чого запустимо наш додаток на виконання і бачимо, що все відображається коректно:

classes
введення

Щоб не повторюватися для iPad, ми робимо все те ж саме, що і для iPhone, тільки в сітці Size Classes вибираємо regular Width regular Height, що відповідає портретній і ландшафтній орієнтації iPad. У цій ситуації ми просто оновили всі Constraint, відцентрували та виставили Width, Height Equally:

xcode
classes

Залишилося 2 пункти, якими не пройшлися, це включення/вимкнення subviews та шрифти. Виберемо ландшафтний режим iPhone compact Width compact Height. Виділимо наш UILabel і перейдемо до Attributes Inspector, навпроти шрифту ми побачимо вже знайомий нам „+“:

Height

За аналогією з Constraint додаємо „compact Width compact Height (current)“. Для значення wC hC виставимо шрифт Helvetica Neue Ultra Light і розмір 23. При запуску ми побачимо що в портретній орієнтації стандартний шрифт а вже в ландшафті Helvetica Neue:

введення
введення

Отже, останній пункт це включення та вимкнення subviews. Я думаю, тут пояснювати вже нічого не треба, і так все зрозуміло після всіх цих розжовування. Все за аналогією з включенням вимкненням Constraint, різниця тільки в тому, що тут ми вимкнемо кнопку для конкретної орієнтації:

classes
classes

Дякую за увагу!

Хардкорна конфа за С++. Ми запрошуємо лише профі.