iOS. Приемы программирования - Вандад Нахавандипур
Шрифт:
Интервал:
Закладка:
5. Чтобы правильно оформить виды верхних и нижних колонтитулов перед тем, как они будут отображены, реализуйте метод collectionView: viewForSupplementaryElementOfKind: atIndexPath: источника данных сборного вида, а в этом методе запустите другой метод сборного вида, dequeueReusableSupplementaryViewOfKind: withReuseIdentifier: forIndexPath:, чтобы извлечь из очереди многоразовый вид верхнего или нижнего колонтитула.
6. Наконец, необходимо убедиться, что размер видов для верхних и нижних колонтитулов задается путем присваивания соответствующих значений свойствам headerReferenceSize и footerReferenceSize макетного объекта, отвечающего за последовательную компоновку.
Обсуждение
Итак, теперь нам требуется создать. xib-файлы для специальных верхних и нижних колонтитулов. Назовем их Header.xib и Footer.xib. Мы создаем их по тому же принципу, который описан в разделе 5.5, поэтому я не буду вновь повторять здесь этот материал. Убедитесь в том, что и для верхнего и для нижнего колонтитула у вас есть по одному классу Objective-C. Назовите их соответственно Header и Footer. Необходимо гарантировать, что оба этих класса наследуют от UICollectionReusableView. Закончив с этим, сконфигурируйте в конструкторе интерфейса подпись и кнопку, затем перетащите подпись в файл Header, а кнопку — в файл Footer. Свяжите их с вашими классами так, как показано на рис. 5.10 и 5.11.
Рис. 5.10. Конфигурирование ячейки верхнего колонтитула для сборного вида в конструкторе интерфейса
Рис. 5.11. Конфигурирование ячейки нижнего колонтитула для сборного вида в конструкторе интерфейса
Я связал подпись из верхнего колонтитула с классом Header с помощью свойства аутлета[4] в файле Header.h. Назовем аутлет просто label:
#import <UIKit/UIKit.h>
@interface Header: UICollectionReusableView
@property (weak, nonatomic) IBOutlet UILabel *label;
@end
То же самое я делаю и в нижнем колонтитуле, связав кнопку из файла Footer.xib с аутлетом из файла Footer.h и назвав аутлет button:
#import <UIKit/UIKit.h>
@interface Footer: UICollectionReusableView
@property (weak, nonatomic) IBOutlet UIButton *button;
@end
Теперь в контроллере сборного вида определим идентификаторы для ячеек верхнего и нижнего колонтитулов:
#import «ViewController.h»
#import «MyCollectionViewCell.h»
#import «Header.h»
#import «Footer.h»
static NSString *kCollectionViewCellIdentifier = @"Cells";
static NSString *kCollectionViewHeaderIdentifier = @"Headers";
static NSString *kCollectionViewFooterIdentifier = @"Footers";
@implementation ViewController
…
Далее в методе-инициализаторе сборного вида зарегистрируем ячейку сборного вида, ячейку верхнего колонтитула и ячейку нижнего колонтитула. Для этого воспользуемся nib-файлами, которые мы загружаем в память:
— (instancetype) initWithCollectionViewLayout:(UICollectionViewLayout *)layout{
self = [super initWithCollectionViewLayout: layout];
if (self!= nil){
/* Регистрируем nib-файл со сборным видом для удобного получения */
UINib *nib = [UINib nibWithNibName:
NSStringFromClass([MyCollectionViewCell class])
bundle: [NSBundle mainBundle]];
[self.collectionView registerNib: nib
forCellWithReuseIdentifier: kCollectionViewCellIdentifier];
/* Регистрируем nib-файл верхнего колонтитула */
UINib *headerNib = [UINib
nibWithNibName: NSStringFromClass([Header class])
bundle: [NSBundle mainBundle]];
[self.collectionView registerNib: headerNib
forSupplementaryViewOfKind: UICollectionElementKindSectionHeader
withReuseIdentifier: kCollectionViewHeaderIdentifier];
/* Регистрируем nib-файл нижнего колонтитула */
UINib *footerNib = [UINib
nibWithNibName: NSStringFromClass([Footer class])
bundle: [NSBundle mainBundle]];
[self.collectionView registerNib: footerNib
forSupplementaryViewOfKind: UICollectionElementKindSectionFooter
withReuseIdentifier: kCollectionViewFooterIdentifier];
}
return self;
}
Переходим к реализации метода collectionView: viewForSupplemen taryElementOfKind: atIndexPath: сборного вида. Этот метод нужен нам для конфигурирования верхних и нижних колонтитулов и предоставления их обратно сборному виду:
— (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView
viewForSupplementaryElementOfKind:(NSString *)kind
atIndexPath:(NSIndexPath *)indexPath{
NSString *reuseIdentifier = kCollectionViewHeaderIdentifier;
if ([kind isEqualToString: UICollectionElementKindSectionFooter]){
reuseIdentifier = kCollectionViewFooterIdentifier;
}
UICollectionReusableView *view =
[collectionView dequeueReusableSupplementaryViewOfKind: kind
withReuseIdentifier: reuseIdentifier
forIndexPath: indexPath];
if ([kind isEqualToString: UICollectionElementKindSectionHeader]){
Header *header = (Header *)view;
header.label.text = [NSString stringWithFormat:@"Section Header %lu",
(unsigned long)indexPath.section + 1];
}
else if ([kind isEqualToString: UICollectionElementKindSectionFooter]){
Footer *footer = (Footer *)view;
NSString *title = [NSString stringWithFormat:@"Section Footer %lu",
(unsigned long)indexPath.section + 1];
[footer.button setTitle: title forState: UIControlStateNormal];
}
return view;
}
Наконец, необходимо убедиться, что макету с последовательной компоновкой известно о том, что в сборном виде есть ячейки верхнего и нижнего колонтитулов. На основе кода, написанного в разделе 5.3, изменим метод flowLayout делегата нашего приложения следующим образом:
— (UICollectionViewFlowLayout *) flowLayout{
UICollectionViewFlowLayout *flowLayout =
[[UICollectionViewFlowLayout alloc] init];
flowLayout.minimumLineSpacing = 20.0f;
flowLayout.minimumInteritemSpacing = 10.0f;
flowLayout.itemSize = CGSizeMake(80.0f, 120.0f);
flowLayout.scrollDirection = UICollectionViewScrollDirectionVertical;
flowLayout.sectionInset = UIEdgeInsetsMake(10.0f, 20.0f, 10.0f, 20.0f);
/* Задаем базовый размер для видов с верхними и нижними колонтитулами */
flowLayout.headerReferenceSize = CGSizeMake(300.0f, 50.0f);
flowLayout.footerReferenceSize = CGSizeMake(300.0f, 50.0f);
return flowLayout;
}
Итак, все готово! Если вы теперь запустите приложение в эмуляторе iPad, то увидите примерно такой результат, как на рис. 5.12.
Рис. 5.12. Верхние и нижние колонтитулы в сборном виде
См. также
Разделы 5.2, 5.3, 5.5.
5.8. Добавление собственных вариантов взаимодействий к сборным видам
Постановка задачи
Вы хотели бы добавить к сборному виду собственные механизмы распознавания жестов, таких как щипок, чтобы реализовать собственные варианты поведений на базе уже имеющихся.
Решение
Инстанцируйте механизм распознавания жестов, а потом просмотрите распознаватели жестов, уже имеющиеся в сборном виде, и проверьте, нет ли среди них такого, который похож на нужный вам. Если найдете такой механизм, вызовите в нем метод requireGestureRecognizerToFail: и передайте этому методу в качестве параметра ваш собственный распознаватель жестов. Так вы гарантируете, что распознаватель жестов, имеющийся в сборном виде и напоминающий тот, что нужен вам, будет в случае необходимости подхватывать обработку жестов. Это станет происходить, если вашему распознавателю жестов не удастся обработать те или иные данные либо данные не будут соответствовать его требованиям/критериям. Таким образом, если ваш распознаватель способен обработать жест, он это сделает, в противном случае жест будет передан механизму распознавания, уже имеющемуся в сборном виде. Этот механизм обработает его сам.
Как только выполните описанную работу, добавьте ваш распознаватель жестов к сборному виду. Как вы помните, в экземпляре UICollectionViewController объект вашего сборного вида будет доступен через свойство контроллера collectionView, а не через свойство view.
Обсуждение
В API iOS уже предусмотрено несколько механизмов обработки жестов, применяемых в сборных видах. Поэтому для добавления собственных распознавателей жестов к уже имеющейся коллекции сначала нужно убедиться в том, что ваши распознаватели жестов не будут функционально пересекаться с уже имеющимися. Для этого сначала нужно инстанцировать ваши собственные распознаватели жестов, а потом, как описано ранее, просмотреть массив таких распознавателей, уже имеющихся у сборного вида. Затем понадобится вызвать метод requireGestureRecognizerToFail: в классе распознавателя жестов того же типа, что и наш распознаватель жестов, который мы собираемся добавить к сборному виду.
Рассмотрим пример. В этом примере мы собираемся добавить к сборному виду возможность уменьшения и увеличения изображения (то есть его масштабирования). Этот пример будет выстроен на основе того, который мы подготовили в разделе 5.5. Итак, первым делом мы должны добавить распознаватель щипков в коллекцию распознавателей жестов, имеющихся в сборном виде. Мы сделаем это в методе viewDidLoad контроллера сборного вида: