SectionIndexTitles for a UICollectionView

后端 未结 4 2116
醉话见心
醉话见心 2020-12-08 01:35

So I implemented a proper TableView with a search functionality and sectionIndexTitles. Now, I am trying to implement a UICollectionView

相关标签:
4条回答
  • 2020-12-08 01:54

    You can now simply use (as of iOS 10.3)

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

    Which expects an array like: ['A', 'B' ,'C'] as its return value.

    0 讨论(0)
  • 2020-12-08 02:04

    You can provide this header by implementing and returning a value for the following function for UICollectionViewDataSource

    collectionView:viewForSupplementaryElementOfKind:atIndexPath:
    

    Note that the size of the header will be from the height value of the CGRect returned from UICollectionViewFlowLayoutDelegate method collectionView:layout:referenceSizeForHeaderInSection:

    0 讨论(0)
  • 2020-12-08 02:07

    I had a similar requirement (for a horizontal collection view) and ended up building an index view subclass myself.

    I plan to open-source it but that will likely have to wait until next month, so here's a stub to get you started:

    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
    

    In your view controller:

    - (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
    
    0 讨论(0)
  • 2020-12-08 02:07

    As of iOS 14 (which has severely enhanced UICollectionView, in particular for making UITableView obsolete), this works as expected by implementing the delegate method indexTitles.

    0 讨论(0)
提交回复
热议问题