效果图
实现逻辑和原理
就是在 didEndDisplayingCell 方法中通过indexPathsForVisibleItems 接口获取当前可见的cell对应的indexPath, 然后获取到item最小的那一个,即可,同时,还要在 willDisplayCell 方法中直接设置标题的选中属性,否则
由于重用机制,导致选中的展示错乱
代码
//
// LBLinkedContentView.m
// LBTwoLinkedScrollingCollectionView
//
// Created by mac on 2024/6/25.
//
#import "LBLinkedContentView.h"
#import "LBLinkedContentViewTittleCell.h"
#import "LBLinkedContentViewContentCell.h"
@interface LBLinkedContentView () <UICollectionViewDelegate, UICollectionViewDataSource>
@property (nonatomic, strong) UICollectionView *titleView;
@property (nonatomic, strong) UICollectionView *contentView;
@property (nonatomic, strong) NSMutableArray *titleArray;
@property (nonatomic, strong) NSMutableArray *contentArray;
@property (nonatomic, strong) NSIndexPath *selectedGroupIndex;
@end
@implementation LBLinkedContentView
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
[self configData];
[self setUpUI];
}
return self;
}
- (void)setUpUI
{
[self addSubview:self.titleView];
[self addSubview:self.contentView];
[self.titleView reloadData];
[self.contentView reloadData];
self.selectedGroupIndex = [NSIndexPath indexPathForRow:0 inSection:0];
LBLinkedContentViewTittleCell *titleCell = [self.titleView cellForItemAtIndexPath:self.selectedGroupIndex];
titleCell.selected = YES;
}
#pragma mark - configData
- (void)configData
{
for (int i = 0; i < 10; i ++) {
NSString *title = [NSString stringWithFormat:@"%d",i];
[self.titleArray addObject:title];
NSMutableArray *array = [NSMutableArray array];
for (int j = 0; j < 10; j ++) {
NSString *content = [NSString stringWithFormat:@"第%d分区第%d条", i,j];
[array addObject:content];
}
[self.contentArray addObject:array];
}
}
#pragma mark - data Delegate
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
if (collectionView == self.contentView) {
LBLinkedContentViewContentCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([LBLinkedContentViewContentCell class]) forIndexPath:indexPath];
NSString *title = self.contentArray[indexPath.section][indexPath.item];
[cell updateWithContent:title];
return cell;
}
LBLinkedContentViewTittleCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([LBLinkedContentViewTittleCell class]) forIndexPath:indexPath];
[cell updateWithIndexPath:indexPath];
return cell;
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
if (collectionView == self.titleView) {
return 1;
}
return self.contentArray.count;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return 10;
}
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
{
if (collectionView == self.titleView) {
if (self.selectedGroupIndex && [self.selectedGroupIndex compare:indexPath] == NSOrderedSame) {
cell.selected = YES;
} else {
cell.selected = NO;
}
}
}
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
{
if (collectionView == self.contentView) {
[self handleGroupViewWithIndex:nil];
}
}
#pragma mark - private
- (void)handleGroupViewWithIndex:(NSIndexPath *)indexPathCell
{
NSArray <NSIndexPath *> *visibleIndexPaths = [self.contentView indexPathsForVisibleItems];
if (!visibleIndexPaths.count) {
return;
}
NSInteger section = indexPathCell ? indexPathCell.section : [self.contentView numberOfSections] - 1;
for (NSIndexPath *indexPath in visibleIndexPaths) {
if (indexPath.section < section) {
section = indexPath.section;
}
}
NSIndexPath *groupIndexPath = [NSIndexPath indexPathForItem:section inSection:0];
if(self.selectedGroupIndex && [self.selectedGroupIndex compare:groupIndexPath] != NSOrderedSame) {
LBLinkedContentViewTittleCell *cell = [self.titleView cellForItemAtIndexPath:self.selectedGroupIndex];
cell.selected = NO;
self.selectedGroupIndex = groupIndexPath;
LBLinkedContentViewTittleCell *titleCell = [self.titleView cellForItemAtIndexPath:groupIndexPath];
titleCell.selected = YES;
[self.titleView scrollToItemAtIndexPath:groupIndexPath atScrollPosition:UICollectionViewScrollPositionLeft animated:YES];
}
}
#pragma mark - lazy load
- (UICollectionView *)titleView
{
if (!_titleView) {
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.minimumLineSpacing = 29;
layout.minimumInteritemSpacing = 29;
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
layout.itemSize = CGSizeMake(40, 50);
_titleView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.bounds), 60) collectionViewLayout:layout];
[_titleView registerClass:[LBLinkedContentViewTittleCell class] forCellWithReuseIdentifier:NSStringFromClass([LBLinkedContentViewTittleCell class])];
_titleView.delegate = self;
_titleView.dataSource = self;
}
return _titleView;
}
- (UICollectionView *)contentView
{
if (!_contentView) {
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.minimumLineSpacing = 10;
layout.minimumInteritemSpacing = 10;
layout.itemSize = CGSizeMake(100, 80);
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
layout.sectionInset = UIEdgeInsetsMake(0, 40, 0, 40);
_contentView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 80, CGRectGetWidth(self.bounds), 80) collectionViewLayout:layout];
[_contentView registerClass:[LBLinkedContentViewContentCell class] forCellWithReuseIdentifier:NSStringFromClass([LBLinkedContentViewContentCell class])];
_contentView.delegate = self;
_contentView.dataSource = self;
_contentView.backgroundColor = [UIColor yellowColor];
}
return _contentView;
}
- (NSMutableArray *)titleArray
{
if (!_titleArray) {
_titleArray = [NSMutableArray array];
}
return _titleArray;
}
- (NSMutableArray *)contentArray
{
if (!_contentArray) {
_contentArray = [NSMutableArray array];
}
return _contentArray;
}
@end
link