Auto Layout зі змінним набором елементів

В Xcode 5 компанія Apple представила нову систему побудови інтерфейсів додатків для iOS (6+) і MAC OS X v10.7 +) «Auto Layout» (AL) покликану замінити застарілу «Springs & Struts» (S&S). Грунтуючись на завданні правил (Constraints) визначають розмір і положення інтерфейсних елементів, AL надає значно ширші можливості ніж S&S. Тим не менш, слабкою стороною AL (крім більшої складності) є робота зі змінними наборами елементів. Сама по собі система AL взагалі не підтримує додаткові елементи, але є способи обійти це обмеження.

Припустимо нам потрібно показувати картки порід кішок, у кожній картці буде назву породи, країна походження та короткий опис. Створимо новий xib файл для нашої картки, додамо в кореневій view три label'а (не забуваючи виставити властивість lines = 0) і встановимо необхідні constraints:


Додамо кілька таких карток в ScrollView:


Тут у нас немає опціональних елементів і все виглядає так, як повинно, але що буде, якщо у нас недостатньо інформації? Наприклад, ми не знаємо країну походження або відсутній опис?



Очевидно розміри label'ів для відсутніх даних стали нульовими, а відступи зверху і знизу просто склалися. Вирішити цю проблему можна декількома способами:

Спосіб перший: видалити непотрібні елементи view при заповненні даних. Разом з видаленням елемента інтерфейсу видаляються і всі пов'язані з ним constraint'и. Правда, якщо просто видалити, наприклад, label країни походження породи, то відступ між назвою і описом буде не визначений. Тому спочатку необхідно додати додаткові constraint'и для випадків видалення кожного з необов'язкових елементів:



Тепер при заповненні даних достатньо викликати для порожніх label'ів метод

(void)removeFromSuperview

і картки будуть формуватися правильно:


У цьому підході є два недоліки:

  • Потрібно вводити багато додаткових constraint'ов (і їх число буде рости зі збільшенням числа опціональних елементів)
  • Оскільки label'и видаляються, одного разу заповнену картку не можна використовувати повторно, оскільки немає гарантії, що набори даних співпадуть. На перший погляд це може здатися несуттєвим, адже завжди можна створити нову картку. Але, якщо нам необхідно показати наші картки не ScrollView, а в CollectionView який реалізує патерн «Об'єктний пул» картки повинні мати можливість повторного використання.
Щоб уникнути цих недоліків доведеться переглянути структуру нашої картки:

  • Зверху і знизу додамо два view фіксованої висоти вони будуть служити для завдання відступів від країв
  • Укладемо кожен label у view.
Додамо constraint'и:


Причому для constraint'ів всередині блоків (позначені пунктиром) встановимо значення пріоритету рівне 750 (High)
Тепер залишилося тільки додати constraint'и для висот:


Спосіб другий: задати висоту блоків з контентом. Змінюючи значення X, Y, Z можна обмежувати максимальну висоту кожного блоку, таким чином, при заповненні картки у разі відсутності вмісту задавати значення висоти блоку 0, а у разі якщо контент є будь-яке значення завідомо перевищує максимально можливу висоту блоку.
Таким чином ми уникнули всіх недоліків попереднього способу: кількість необхідних constraint'ів не збільшується пропорційно кількості опціональних елементів і картка може бути використана повторно.

Висновки:

Якщо не потрібно повторне використання і кількість опціональних елементів невелика то краще додати додаткові constraint'и і видаляти непотрібні елементи при заповненні даних. У випадку коли потрібно повторне використання, або багато опціональних елементів варто розбити інтерфейс на блоки і для порожніх блоків встановлювати висоту дорівнює 0.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.