21

所以我实现了一个TableView带有搜索功能的适当的和sectionIndexTitles. 现在,我正在尝试实现 aUICollectionView并且到目前为止它正在工作,除了我不能轻易拥有sectionIndexTitles(右滚动条)。

如果我查看 Facebook 应用程序,它看起来像一个UICollectionView,但确实sectionIndexTitles有一个搜索栏。我似乎找不到该UICollectionView模型的此类功能。

有任何想法吗?!

谢谢!

在此处输入图像描述

4

5 回答 5

16

我有类似的要求(对于水平集合视图)并最终自己构建了一个索引视图子类。

我计划开源它,但可能要等到下个月,所以这里有一个存根让你开始:

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
于 2013-01-21T16:57:36.587 回答
2

从 iOS 14 开始(已大大增强UICollectionView,尤其是UITableView过时),通过实现委托方法可以按预期工作indexTitles

于 2020-10-30T12:08:30.270 回答
1

索引标题确实适用于 iOS,但在我测试时它似乎只适用于 iOS 14+。

func indexTitles(for collectionView: UICollectionView) -> [String]? {
    return Array(Set(objects.map{ String($0.name.prefix(1)) })).sorted(by: { $0 < $1 })
}

func collectionView(_ collectionView: UICollectionView, indexPathForIndexTitle title: String, at index: Int) -> IndexPath {
    guard let index = objects.firstIndex(where: { $0.name.prefix(1) == title }) else {
        return IndexPath(item: 0, section: 0)
    }
    return IndexPath(item: index, section: 0)
}
于 2020-12-28T15:58:33.867 回答
0

编辑:这已被验证已修复,并且现在可以在 iOS 14 中按预期工作

您现在可以简单地使用(从 iOS 10.3 开始)

optional func indexTitles(for collectionView: UICollectionView) -> [String]?

它需要一个数组,如: ['A', 'B' ,'C'] 作为它的返回值。

于 2017-06-19T15:02:57.773 回答
-1

您可以通过实现并返回UICollectionViewDataSource的以下函数的值来提供此标头

collectionView:viewForSupplementaryElementOfKind:atIndexPath:

请注意,标头的大小将来自UICollectionViewFlowLayoutDelegate方法 collectionView:layout:referenceSizeForHeaderInSection 返回的 CGRect 的高度值:

于 2012-12-15T20:08:57.027 回答