UICollectionView - Коллекции видовых представлений

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

Реализация:
  • Коллекции видовых представлений реализованы в классе UICollectionView.
  • Ячейки коллекции видовых представлений реализованы в классе UICollectionViewCell.
  • Ячейки для многократного использования реализованы в классе UICollectionReusableView.

Контент для коллекции видов

Ячейки представляют основной контент коллекции видов. Основная задача одной ячейки - представить один элемент из источника данных коллекции видов. Каждая ячейка должна быть потомком класса UICollectionViewCell.

Для обеспечения визуального отображения данных, коллекции видов работают с несколькими родственными классами, такими как: UICollectionViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionReusableView, UICollectionViewCell, UICollectionViewLayout, UICollectionViewLayoutAttributes.

 

Классы и протоколы для реализации коллекции видов:

ОбеспечиваетКласс / ПротоколОписание
Верхний уровень и управление
UICollectionView
UICollectionViewController

UICollectionView предоставляет визуальную площадку для контента коллекции видов. Данный класс наследуется от UIScrollView и может содержать большую площадь со скроллингом. Данный класс также облегчает представление ваших данных.

UICollectionViewController предоставляет поддержку для управления коллекцией видов. Его использование необязательно.

Управление контентом
UICollectionViewDataSource протокол
UICollectionViewDelegate протокол

Объект data source самый важный объект, созданный вами, только этот объект знает как представить ваши данные для коллекции видов. Создаваемый вами объект управления данными должен реализовывать UICollectionViewDataSource протокол.

Объект delegate предоставляет возможность перехватывать события от коллекции видов и настраивать пользовательское поведение представления коллекции видов, например подсветку выбранных ячеек коллекции. Данный протокол является необязательным.

Представление
UICollectionReusableView
UICollectionViewCell

Все виды отображаемые коллекцией видов должны быть экземплярами класса UICollectionReusableView. Данный класс поддерживает механизм рециркуляции, используемый коллекцией видов.

Объект UICollectionViewCell представляет собой специфичный объект рециркулируемого вида для вашей ячейки с данными.

Слой
UICollectionViewLayout
UICollectionViewLayoutAttributes
UICollectionViewUpdateItem

Подклассы UICollectionViewLayout задают положение, размер и визуальные атрибуты для ячеек и переиспользуемых видов внутри коллекции видов.

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

Объект Слоя получает экземпляр класса UICollectionViewUpdateItem, во время вставки, удаления или перемещения данных внутри коллекции видов. У вас нет необходимости в создании экземпляра данного класса.

Слой подачи
UICollectionViewFlowLayout
UICollectionViewDelegateFlowLayout протокол

Класс UICollectionViewFlowLayout является тем самым объектом слоя, с помощью которого вы реализуете сетку или другие табличные элементы. Вы можете использовать данный класс как есть или в сочетании с делегатом (UICollectionViewDelegateFlowLayout) для динамического управления информацией.

 

Создание коллекции видов

Создание коллекции видов всегда начинается с добавления объекта UICollectionView в ваш storyboard или nib файл. Далее вы конфигурируете ваш объект коллекции видов, добавляя источник данных (data source), делегат (delegate) и т.д.. Вы никогда не создаете какие либо классы по управлению коллекцией вида без коллекции вида. Например вы не можете создать объекты слоев, не создав сам объект коллекции видов.

Переиспользуемые виды повышают производительность

Коллекции видов используют технологию по утилизации видов, для повышения производительности. Как только вид перемещается за поле отображения, он удаляется из вида и ставится в очередь вместо удаления. При скролинге нового контента вид извлекается из очереди с новым содержимым. Чтобы воспользоваться данной технологией, все виды в коллекции видов должны быть унаследованы от класса UICollectionReusableView.

Проектирование вашего объекта данных и делегата

Каждый объект Collection View должен иметь источник данных (datasource), который предоставляет контент для отображения вашим приложением. Это может быть объект модели данных или контроллер вида, управляемый коллекцией видов. Все, что требуется от источника данных,- это предоставить информацию коллекции видов о том сколько ячеек необходимо пердставить и какие видовые представления отобразить.

UICollectionViewDataSource предоставляет протокол для источника данных коллекции видов.

    Количество секций и ячеек

  • - numberOfSectionsInCollectionView: - Возвращает количество секций для Collection View, если не реализован, возвращает 1.
  • - collectionView:numberOfItemsInSection: - Возвращает количество ячеек для секции, обязательный метод.

    Предоставление видов для Collection View

  • - collectionView:cellForItemAtIndexPath: - Обязательный метод, в реализации которого вы возвращаете созданный и сконфигурированный объект UICollectionViewCell. В большинстве случаев вы выполняете дизайн макета для ячейки в Interface Builder и создаете объект ячейки на основе этого макета с помощью метода - dequeueReusableCellWithReuseIdentifier:forIndexPath:, который возвращает ячейку, сконфигурированную для размещения в заданной в IndexPath позиции в коллекции видов.
  • - collectionView:viewForSupplementaryElementOfKind:atIndexPath: - Возвращает вспомогательный переиспользуемый вид для коллекции видов, такой как верхний и нижний заголовок секции. Реализация этого метода необязательна.

Пример реализации Collection View

В данном примере рассмотрим Коллекцию видов с одной секцией и ячейками, содержащими элементы Image view и Label.

Создадим в Xcode новый проект Single View Application. Переходим в Main.storyboard и удаляем созданный Xcode View Controller, и вместо него добавляем Collection View Controller. Теперь переходим в редактор ViewController.h и меняем наследуемый класс UIViewController на UICollectionViewController, должно выглядеть так: @interface ViewController : UICollectionViewController. Возвращаемся в Main.storyboard и устанавливаем для Collection View Controller класс ViewController, а также устанавливаем Is Initial View Controller. В данном примере выставляем для Collection View белый Background. Теперь регулируем Ячейку: первое, что необходимо сделать это задать для нее Identifier, в нашем примере cellItem. Следующий шаг,- размещение в ячейке элементов Image View и Label.

Теперь создадим класс, унаследованный от NSObject, для одного элемента источника данных, который будет предоставлять строку с наименованием и изображение для Collection View.

Реализация mbFruitData.h

#import <UIKit/UIKit.h>

@interface mbFruitData : NSObject

@property (nonatomic, retain) NSString* nameProduct;
@property (nonatomic, retain) UIImage* imgProduct;

@end

Заметим, что Xcode, по крайней мере шестая версия, создает унаследованные классы от NSObject с импортом Foundation библиотеки, которая ничего не знает о UIImage, поэтому заменяем импорт на UIKit!

Файл реализации mbFruitData.m оставляем без изменений.

Теперь добавим несколько файлов с картинками, в нашем случае три: apple.jpg, apples.jpg, apricot.jpg размером 180 х 180 пикселей.

Теперь настала очередь создать класс, унаследованный от UICollectionViewCell, который будет представлять нашу ячейку в коллекции видов.

Реализация mbCVReuse.h

#import <UIKit/UIKit.h>

@interface mbCVReuse : UICollectionViewCell
{
  
}
@property (strong, nonatomic) IBOutlet UIImageView *img;
@property (strong, nonatomic) IBOutlet UILabel *tfLabel;


@end

Переходим в Interface Builder, выделяем ячейку и назначаем для нее класс mbCVReuse. Далее соединяем элементы ячейки с соответствующими свойствами, как показано ниже:

Теперь переходим в ViewController.h и добавляем переменную NSMutableArray* arrItems, которая будет содержать массив с экземплярами классов mbFruitData.h. И наконец отредактируем ViewController.h, в котором заполним этот массив, а также реализуем UICollectionViewDataSource протокол.

Реализация ViewController.h

#import <UIKit/UIKit.h>

@interface ViewController : UICollectionViewController
{
  NSMutableArray* arrItems;
}


@end

Реализация ViewController.m

#import "ViewController.h"
#import "mbFruitData.h"
#import "mbCVReuse.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  // Do any additional setup after loading the view, typically from a nib.
  
  // Создаем массив с данными для Collection View
  arrItems = [NSMutableArray arrayWithCapacity:3];
  
  mbFruitData* fru = [[mbFruitData alloc] init];
  fru.nameProduct = @"Яблоко";
  fru.imgProduct = [UIImage imageNamed:@"apple.jpg"];
  [arrItems addObject:fru];
  
  fru = [[mbFruitData alloc] init];
  fru.nameProduct = @"Яблоки";
  fru.imgProduct = [UIImage imageNamed:@"apples.jpg"];
  [arrItems addObject:fru];
  
  fru = [[mbFruitData alloc] init];
  fru.nameProduct = @"Абрикос";
  fru.imgProduct = [UIImage imageNamed:@"apricot.jpg"];
  [arrItems addObject:fru];
}

- (void)didReceiveMemoryWarning {
  [super didReceiveMemoryWarning];
  // Dispose of any resources that can be recreated.
}

- (NSInteger)collectionView:(UICollectionView *)collectionView
     numberOfItemsInSection:(NSInteger)section
{
  // Количество ячеек, в нашем примере одна секция, поэтому section не имеет значения
  return arrItems.count;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
                  cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
  // создаем и инициализируем ячейку на основе шаблона
  mbCVReuse* cv = [collectionView dequeueReusableCellWithReuseIdentifier:@"cellItem" forIndexPath:indexPath];
  NSInteger row = indexPath.row;
  mbFruitData* item = arrItems[row];
  cv.tfLabel.text = item.nameProduct;
  cv.img.image = item.imgProduct;
  
  return cv;
}

@end

Данный пример конечно весьма примитивен, но он показывает пример реализации Коллекции видов и протокола источника данных.

Реализация делегата

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

Делегат коллекции видов предоставляет следующие методы для отслеживания касания и выбора ячеек:

  • collectionView:shouldSelectItemAtIndexPath: - возвращает YES если ячейка может быть выбрана, значение по умолчанию YES.
  • collectionView:shouldDeselectItemAtIndexPath: - возвращает YES если заданная ячейка может быть невыбрана, значение по умолчанию YES.
  • collectionView:didSelectItemAtIndexPath: - вызывается если ячейка была удачно выбрана.
  • collectionView:didDeselectItemAtIndexPath: - вызывается, если выбранная ячейка была скинута.
  • collectionView:shouldHighlightItemAtIndexPath: - возвращает YES если ячейка может быть подсвечена во время касания, значение по умолчанию YES.
  • collectionView:didHighlightItemAtIndexPath: - вызывается при касании ячейки для подсветки.
  • collectionView:didUnhighlightItemAtIndexPath: - вызывается, чтобы сообщить об окончании подсветки.

Вы можете использовать приведенные методы для индикации выбора и подсветки ячеек, например путем изменения свойства backgroundColor видового представления ячейки, как показано ниже:

- (void)collectionView:(UICollectionView *)colView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath {
  UICollectionViewCell* cell = [colView cellForItemAtIndexPath:indexPath];
  cell.contentView.backgroundColor = [UIColor yellowColor];
}

- (void)collectionView:(UICollectionView *)colView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath {
  UICollectionViewCell* cell = [colView cellForItemAtIndexPath:indexPath];
  cell.contentView.backgroundColor = nil;
}

- (void)collectionView:(UICollectionView *)colView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
  UICollectionViewCell* cell = [colView cellForItemAtIndexPath:indexPath];
  cell.contentView.backgroundColor = [UIColor blueColor];
}

- (void)collectionView:(UICollectionView *)colView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath
{
  UICollectionViewCell* cell = [colView cellForItemAtIndexPath:indexPath];
  cell.contentView.backgroundColor = nil;
}

 

Вывод меню редактирования

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

  • collectionView:shouldShowMenuForItemAtIndexPath: - возвращает YES если меню может быть отображено для заданной ячейки. Значение по умолчанию NO.
  • collectionView:canPerformAction:forItemAtIndexPath:withSender: - возвращает YES если ячейка поддерживает заданную команду, команда может быть одной из трех: cut:, copy:, paste:.
  • collectionView:performAction:forItemAtIndexPath:withSender: - вызывается если ячейка должна выполнить заданную команду.

В следующем примере добавим возможность копировать и вставлять ячейки в созданный ранее проект с фруктами. Добавим переменную в ViewController.h NSInteger copyIndex; и в метод - (void)viewDidLoad добавим строку copyIndex = -1;. Ниже приведены методы делегата для копирования и вскавки ячейки из нашего примера:

- (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath{
  return YES;
}

- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action
    forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender{
  NSString* s = NSStringFromSelector(action);
  BOOL result;
  if([s isEqualToString:@"copy:"] || [s isEqualToString:@"paste:"])
    result = YES;
  else
    result = NO;
  return result;
}

- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action
      forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender{
  NSString* s = NSStringFromSelector(action);
  if([s isEqualToString:@"copy:"])
    copyIndex = indexPath.row;
  else if(copyIndex!=-1) {// paste
    mbFruitData* fru = arrItems[copyIndex];
    [arrItems insertObject:fru atIndex:indexPath.row];
    [collectionView reloadData];
  }
}

В этом примере мы просто сохраняем индекс копируемой ячейки, и вставляем тот-же самый объект данных в массив объекта данных при выборе "вставить" перед выбранной ячейкой.

 
 
homeЗаметили ошибкукарта сайта 
   Made on a Mac