Раскадровка iOS: как обрабатывать динамический плавающий контент?

Мое приложение содержит раздел новостей. Я пытаюсь создать представление в своей раскадровке, в котором будет отображаться новость. Новость состоит из заголовка, даты, изображения и некоторого текста.

Такой контент было бы легко отобразить в HTML, поскольку его содержимое является плавающим, но, насколько я понимаю, элементы iOS имеют фиксированный размер. Я думаю, что UILabel может подойти для заголовка и даты, UIImage для изображения и UITextView для текста. Я думаю, что все элементы должны быть внутри прокрутки. Проблема в том, что заголовок для некоторых новостей будет занимать одну строку, а для других новостей - несколько строк.

Как я могу справиться с такой настройкой в ​​​​раскадровке? Ссылка на руководство, учебник было бы хорошо.


person dhrm    schedule 07.12.2011    source источник


Ответы (1)


Есть много разных способов приблизиться к этому. В конечном итоге вы можете контролировать размер любого из этих элементов во время выполнения. С точки зрения UX вы, вероятно, захотите сохранить фиксированный размер по крайней мере некоторых элементов (например, изображение и прокрутка, представляющие общий размер элемента новостей). Это оставило бы игру с относительными размерами заголовка и деталей. Если вы хотите отобразить весь заголовок, вы можете использовать метод sizeWithFont (или одну из его вариаций) класса NSString, чтобы вычислить, сколько места нужно использовать для заголовка, и выделить место из оставшейся суммы для деталей по желанию.

ОБНОВЛЕНО: я мог бы добавить, что я задумал это как общую стратегию, а не специально для новой функциональности раскадровки iOS 5.

ОБНОВЛЕНО: Ну, никакого туториала, но вот несколько общих рекомендаций (по крайней мере, о том, как я могу с этим справиться).

Я бы создал класс NewsItem, который инкапсулирует элементы, описанные здесь, подобно тому, что я представил в примере изображения. Как вы разоблачаете NewsItem, это дело вкуса; вы можете начать с UITableView в качестве контейнера, так как это упростит управление коллекцией NewsItem. Я бы подклассировал UITableViewCell как NewsItemTableViewCell и сгенерировал номинальный макет для NewsItem с помощью Interface Builder. Таким образом, в примере изображения элемент новостей будет соответствовать одной строке таблицы.

Основная часть, о которой вы спрашиваете, обозначена красной и синей рамками на изображении. Используя описанный выше подход, я бы добавил логику в NewsItemTableViewCell для вычисления объема заголовка — это предполагает, что представление (в данном случае NewsItemTableViewCell) имеет явное знание модели (базовые данные для элемента новостей) в форма ссылки (т. е. экземпляр класса NewsItem, который содержит описанные вами элементы, извлеченные из веб-службы). Если ширина заголовка больше ширины красной рамки по умолчанию, я бы отрегулировал высоту красной рамки (увеличив ее), одновременно уменьшив высоту синей рамки. Такой подход позволяет избежать необходимости включать дополнительную логику для разной высоты ячеек в таблице.

Альтернативой, которую я часто использую, является использование класса Controller в качестве посредника между представлением и моделью. Это может быть полезно, когда у вас есть требование, чтобы ваша таблица содержала разные типы ячеек; это также значительно упрощает повторное использование ячеек таблицы. В этом случае объявите базовый класс. Это может выглядеть примерно так:

@protocol GenericCellController

- (UITableViewCell*) tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath;
@optional
- (void) tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath;

@end

а потом:

@interface NewsItemTableCellController : NSObject<GenericCellController> {
    NewsItem* newsitem;
}

Затем вы настраиваете коллекцию объектов контроллера ячейки таблицы. Преимущество этого заключается в том, что при реализации tableView:cellForRowAtIndexPath: в коде контроллера табличного представления вам нужно делегировать объект контроллера ячейки только в соответствующей строке. Более того, вы можете ссылаться на него, используя обозначение суперкласса; например, в гипотетическом классе NewsItemTableViewController у вас может быть:

- (UITableViewCell*) tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*) path {
    NSObject<GenericCellController>* cellController = [cellControllerArray objectAtIndexPath:indexPath.row];
    UITableViewCell* cell = [cellController tableView:tableView cellForRowAtIndexPath:indexPath];
    return cell;
}

Этот подход позволяет иметь в коллекции любой класс, производный от NSObject, и полиморфно использовать делегирование, чтобы производный класс обрабатывал логику рендеринга. Производный класс Controller имеет собственную реализацию tableView:cellForRowAtIndexPath: с соответствующим производным от UITableViewCell подклассом, как описано выше.

Если вы решите пойти по этому пути, существует множество примеров основ табличных представлений и их контроллеров, которые вы можете использовать в качестве предисловия к реализации этих идей.

введите здесь описание изображения

person jstevenco    schedule 07.12.2011