РазделIndexTitles для UICollectionView
Итак, я реализовал правильный TableView
с функцией поиска и sectionIndexTitles
. Теперь я пытаюсь реализовать UICollectionView
, и он работает до сих пор, за исключением того, что я не могу легко иметь sectionIndexTitles
(правую полосу прокрутки).
Если я посмотрю приложение Facebook, оно выглядит как UICollectionView
, но действительно sectionIndexTitles
и поисковая панель. Я не могу найти такие функции для модели UICollectionView
.
Любые идеи?!
Спасибо!
![enter image description here]()
Ответы
Ответ 1
У меня было аналогичное требование (для представления горизонтальной коллекции), и в итоге я сам создал подкласс индекса.
Я планирую использовать его с открытым исходным кодом, но это, вероятно, придется ждать до следующего месяца, так что вот здесь будет заглушка:
YMCollectionIndexView.h
@interface YMCollectionIndexView : UIControl
- (id) initWithFrame:(CGRect)frame indexTitles:(NSArray *)indexTitles;
// Model
@property (strong, nonatomic) NSArray *indexTitles; // NSString
@property (readonly, nonatomic) NSUInteger currentIndex;
- (NSString *)currentIndexTitle;
@end
YMCollectionIndexView.m
#import "YMCollectionIndexView.h"
@interface YMCollectionIndexView ()
@property (readwrite, nonatomic) NSUInteger currentIndex;
@property (strong, nonatomic) NSArray *indexLabels;
@end
@implementation YMCollectionIndexView
- (id) initWithFrame:(CGRect)frame indexTitles:(NSArray *)indexTitles {
self = [super initWithFrame:frame];
if (self) {
self.indexTitles = indexTitles;
self.currentIndex = 0;
// add pan recognizer
}
return self;
}
- (void)setIndexTitles:(NSArray *)indexTitles {
if (_indexTitles == indexTitles) return;
_indexTitles = indexTitles;
[self.indexLabels makeObjectsPerformSelector:@selector(removeFromSuperview)];
[self buildIndexLabels];
}
- (NSString *)currentIndexTitle {
return self.indexTitles[self.currentIndex];
}
#pragma mark - Subviews
- (void) buildIndexLabels {
CGFloat cumulativeItemWidth = 0.0; // or height in your (vertical) case
for (NSString *indexTitle in self.indexTitles) {
// build and add label
// add tap recognizer
}
self.indexLabels = indexLabels;
}
#pragma mark - Gestures
- (void) handleTap:(UITapGestureRecognizer*)recognizer {
NSString *indexTitle = ((UILabel *)recognizer.view).text;
self.currentIndex = [self.indexTitles indexOfObject:indexTitle];
[self sendActionsForControlEvents:UIControlEventTouchUpInside];
}
// similarly for pan recognizer
@end
В вашем представлении контроллер:
- (void)viewDidLoad {
[super viewDidLoad];
[self.collectionIndexView addTarget:self action:@selector(indexWasTapped:) forControlEvents:UIControlEventTouchUpInside];
// similarly for pan recognizer
}
- (void)indexWasTapped:(id)sender {
[self.collectionView scrollToIndexPath:...];
}
// similarly for pan recognizer
Ответ 2
Вы нашли решение?
Я пытаюсь реализовать те же функции для UICollectionView.
До сих пор для sectionIndexTitles я использую пользовательский UITableView с теми же разделами, что и исходный UICollectionView, но с пустыми ячейками. В результате у меня есть класс IndexTableView
indexTableView = [[IndexTableView alloc] initWithFrame:CGRectZero];
[self.view addSubview:indexTableView];
...
indexTableView.frame = CGRectMake(CGRectGetWidth(self.view.frame) - 40, 0, 40, CGRectGetHeight(self.view.frame));
indexTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
indexTableView.sectionHeaderHeight = 0;
indexTableView.backgroundColor = [UIColor clearColor];
Я добавляю IndexTableView поверх UICollectionView и получаю тот же визуальный эффект, что и оригинальный UITableView.
Теперь я пытаюсь связать выбор индекса и UICollectionView и заставить его работать.
Редакция:
Я только что добавил UISearchBar в UICollectionController
добавьте следующий код в ваш подкласс UICollectionController
- (void)viewDidLoad
{
[super viewDidLoad];
...
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, self.collectionView.frame.size.width, 44)];
self.searchBar.autocorrectionType = UITextAutocorrectionTypeNo;
self.searchBar.delegate = self;
[self.collectionView addSubview:self.searchBar];
[self.collectionView setContentOffset:CGPointMake(44, 0)];
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
if (section == 0) {
return UIEdgeInsetsMake(CGRectGetHeight(self.searchBar.frame), 6, 0, 6);
}
return UIEdgeInsetsMake(0, 6, 0, 6);
}
Ответ 3
Вы можете использовать следующий пользовательский класс в качестве расширения. пример
Ответ 4
Теперь вы можете просто использовать (с iOS 10.3)
optional func indexTitles(for collectionView: UICollectionView) -> [String]?
Что ожидает массив вроде:
['A', 'B' ,'C']
как его возвращаемое значение.
Ответ 5
Вы можете предоставить этот заголовок, выполнив и вернув значение для следующей функции для UICollectionViewDataSource
collectionView:viewForSupplementaryElementOfKind:atIndexPath:
Обратите внимание, что размер заголовка будет от значения высоты CGRect, возвращаемого из UICollectionViewFlowLayoutDelegate метод collectionView: layout: referenceSizeForHeaderInSection: