用于UICollectionView的SectionIndexTitles

时间:2012-12-14 15:55:57

标签: ios ios5 ios6 uicollectionview

因此,我使用搜索功能和TableView实施了正确的sectionIndexTitles。现在,我正在尝试实现UICollectionView并且它到目前为止工作,除了我不能轻易拥有sectionIndexTitles(右滚动条)。

如果我查看Facebook应用程序,它看起来像UICollectionView,但确实是sectionIndexTitles和搜索栏。我似乎无法为UICollectionView模型找到这样的函数。

有什么想法吗?!

谢谢!

enter image description here

6 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

从iOS 14开始(已对UICollectionView进行了重大增强,尤其是使UITableView过时),此方法可以通过实现委托方法indexTitles来实现。

答案 2 :(得分:0)

您找到了解决方案吗?

我正在尝试为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];

我在UICollectionView的顶部添加了IndexTableView,并获得了与原始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 :(得分:0)

索引标题确实适用于 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)
}

答案 4 :(得分:-1)

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

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

哪个阵列喜欢: ['A', 'B' ,'C'] 作为其返回值。

答案 5 :(得分:-2)

您可以通过为UICollectionViewDataSource

实现并返回以下函数的值来提供此标头
collectionView:viewForSupplementaryElementOfKind:atIndexPath:

请注意,标题的大小将来自UICollectionViewFlowLayoutDelegate方法collectionView:layout:referenceSizeForHeaderInSection:

返回的CGRect的高度值