Статьи

Использование статического UITableView в качестве устройства макета: возьмите два

В то время как ограничения макета и новый  UIStackView класс значительно упростили создание приложений, которые автоматически реагируют на изменения размера и ориентации устройства, иногда пропускается еще один вариант реализации автоматического размещения: UITableView, Начиная с iOS 8, табличные представления поддерживают ячейки «самоизмерения», что позволяет разработчикам создавать сложные пользовательские интерфейсы на основе таблиц без необходимости вручную вычислять высоту ячеек. Поскольку табличные представления часто составляют большую часть пользовательского интерфейса приложения iOS, использование ячеек с самоопределением размера может значительно сократить общее время разработки. Кроме того, эта возможность распространяется на пользовательские ячейки — если ячейка определяет ограничения, которые однозначно определяют положение каждого подпредставления, содержимое ячейки будет автоматически размечаться по мере необходимости в табличном представлении. Нет ручного расчета размера или кода макета не требуется.

Хороший пример использования ячеек таблицы с самоопределением размера можно найти здесь:

http://www.oliverfoggin.com/using-a-static-uitableview-as-a-layout-device/

Этот пример, написанный Оливером Фоггином, использует два табличных представления. Первый вид таблицы представляет список животных для пользователя. Нажатие на строку в этом представлении представляет собой второе табличное представление, которое отображает подробную информацию о выбранном животном, включая имя, латинское имя, изображение и описание, а также имя и изображение автора.

В подробном представлении используются автоматически изменяющиеся ячейки статического представления таблицы и ограничения макета для автоматического упорядочения его содержимого. Структура подробного представления определяется в раскадровке. Я был вдохновлен, чтобы попытаться повторить этот макет, используя MarkupKit. Окончательные результаты показаны ниже:

(после прокрутки)

Разметка, используемая для создания макета (определена в файле с именем  AnimalDetailTableView.xml ), выглядит следующим образом:

<?xml version="1.0" encoding="UTF-8"?>

<LMTableView separator backgroundColor="#ffffff" estimatedSectionHeaderHeight="0" estimatedSectionFooterHeight="0">
    <!-- Name and Latin name -->
    <LMTableViewCell>
        <LMColumnView>
            <UILabel id="titleLabel" font="headline"/>
            <UILabel id="dateLabel" font="footnote"/>
        </LMColumnView>
    </LMTableViewCell>

    <!-- Photo -->
    <LMTableViewCell>
        <UIImageView id="articleImageView" height="200" contentMode="scaleAspectFit"/>
    </LMTableViewCell>

    <!-- Text -->
    <LMTableViewCell>
        <UILabel id="articleTextView" numberOfLines="0"/>
    </LMTableViewCell>

    <!-- Author details -->
    <LMTableViewCell>
        <LMColumnView>
            <LMRowView layoutMarginTop="10" layoutMarginLeft="40" layoutMarginBottom="15" layoutMarginRight="40">
                <UIView height="2" backgroundColor="#666666"/>
            </LMRowView>

            <UIImageView id="authorImageView" height="92" contentMode="scaleAspectFit"/>
            <UILabel id="authorNameLabel" font="footnote" textAlignment="center"/>
        </LMColumnView>
    </LMTableViewCell>
</LMTableView>

LMTableView является подклассом,  UITableView который действует как собственный источник данных и делегат, обслуживая ячейки из статически определенной коллекции разделов табличного представления. LMTableViewCell является подклассом,  UITableViewCell который обеспечивает средство для пользовательского содержимого ячейки. Он автоматически применяет ограничения к своему содержимому, чтобы включить поведение для определения размера.

LMRowView и  LMColumnView являются видами компоновки, которые размещают свои подпредставления в горизонтальной или вертикальной линии соответственно. Они похожи,  UIStackView но имеют некоторые уникальные свойства, такие как возможность распределять подпредставления по весу, а также указывать цвет фона. Они также работают в iOS 8. См.  Эту статью  для получения дополнительной информации.

Первая ячейка использует вид столбца, чтобы расположить метки имени и латинского имени в вертикальной линии внутри ячейки. Атрибут «id» определяет розетки для меток, используя те же имена розеток, которые использовались в оригинальной раскадровке («titleLabel» и «dateLabel»). Как и в оригинале, надписи используют стили динамического текста «заголовок» и «сноска»:

<!-- Name and Latin name -->
<LMTableViewCell>
    <LMColumnView>
        <UILabel id="titleLabel" font="headline"/>
        <UILabel id="dateLabel" font="footnote"/>
    </LMColumnView>
</LMTableViewCell>

Вторая ячейка содержит представление изображения с именем articleImageView, которое отображает изображение животного. Как и в оригинальной раскадровке, высота представления изображения ограничена 200 пикселями. Точно так же третья ячейка содержит метку с именем articleTextView, которая отображает описание животного:

<!-- Photo -->
<LMTableViewCell>
    <UIImageView id="articleImageView" height="200" contentMode="scaleAspectFit"/>
</LMTableViewCell>

<!-- Text -->
<LMTableViewCell>
    <UILabel id="articleTextView" numberOfLines="0"/>
</LMTableViewCell>

Последняя ячейка содержит вид столбца, который отображает имя автора и изображение. Высота изображения ограничена 92 пикселями, а в названии названия используется стиль «сноска», как в оригинале. Представление столбца также содержит пустую строку,  UIView которая используется для создания разделителя шириной 2 пикселя, найденного в исходной версии. Представление строки используется, чтобы установить поля вокруг представления разделителя:

<!-- Author details -->
<LMTableViewCell>
    <LMColumnView>
        <LMRowView layoutMarginTop="10" layoutMarginLeft="40" layoutMarginBottom="15" layoutMarginRight="40">
            <UIView height="2" backgroundColor="#666666"/>
        </LMRowView>

        <UIImageView id="authorImageView" height="92" contentMode="scaleAspectFit"/>
        <UILabel id="authorNameLabel" font="footnote" textAlignment="center"/>
    </LMColumnView>
</LMTableViewCell>

Добавление следующего метода в  AnimalDetailTableViewController класс для загрузки представления из разметки — все, что мне нужно для замены макета на основе раскадровки версией MarkupKit:

- (void)loadView
{
    self.view = [LMViewBuilder viewWithName:@"AnimalDetailTableView" owner:self root:nil];
}

Никаких других изменений не требовалось! Фактически,  tableView:heightForRowAtIndexPath:метод  AnimalDetailTableViewController и подробный вид сцены в раскадровке могут быть фактически удалены, поскольку они не нужны для версии разметки. Кроме того, хотя эта реализация использовала разметку для определения структуры табличного представления, тот же результат мог бы быть достигнут программно. Хотя разметка часто более удобна, все классы представлений MarkupKit также могут использоваться в коде.

Для получения дополнительной информации о MarkupKit, включая дополнительные примеры табличного представления, см.  Вики проекта .