Подтвердить что ты не робот

РазделIndexTitles для UICollectionView

Итак, я реализовал правильный TableView с функцией поиска и sectionIndexTitles. Теперь я пытаюсь реализовать UICollectionView, и он работает до сих пор, за исключением того, что я не могу легко иметь sectionIndexTitles (правую полосу прокрутки).

Если я посмотрю приложение Facebook, оно выглядит как UICollectionView, но действительно sectionIndexTitles и поисковая панель. Я не могу найти такие функции для модели UICollectionView.

Любые идеи?!

Спасибо!

enter image description here

4b9b3361

Ответ 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: