How to Use JJCollectionViewRoundFlowLayout with IGListCollectionView Delegate: Complete Integration Guide
Use the SQCollectionRoundFlowLayout wrapper class to bridge JJCollectionViewRoundFlowLayout with IGListKit by forwarding delegate calls to your IGListSectionController implementations.
JJCollectionViewRoundFlowLayout provides rounded backgrounds, shadows, and borders for UICollectionView sections, but integrating it with IGListKit requires special handling since the IGListAdapter owns the collection view's delegate. In the kingjiajie/jjcollectionviewroundflowlayout repository, the SQCollectionRoundFlowLayout class solves this by routing JJCollectionViewDelegateRoundFlowLayout protocol methods to the appropriate section controllers.
Architecture Overview
The integration relies on a delegation-forwarding pattern that preserves IGListKit's data-driven architecture while allowing per-section customization of rounded decorations.
| Component | Role | Key Source |
|---|---|---|
JJCollectionViewRoundFlowLayout |
Core layout class that draws section background decorations, computes insets, shadows, and alignment. | JJCollectionViewRoundFlowLayout/Classes/JJCollectionViewRoundFlowLayout.h |
JJCollectionViewDelegateRoundFlowLayout |
Protocol defining per-section customization methods including configuration models and border insets. | JJCollectionViewRoundFlowLayout/Classes/JJCollectionViewRoundFlowLayout.h |
SQCollectionRoundFlowLayout |
Subclass that forwards all delegate calls to the IGListAdapter's section controller for each index. |
Example/JJCollectionViewRoundFlowLayout/SQCollectionRoundFlowLayout.h Example/JJCollectionViewRoundFlowLayout/SQCollectionRoundFlowLayout.m |
IGListSectionController |
Your subclass implements delegate methods to customize the rounded background for its specific section. | Referenced in Example/JJCollectionViewRoundFlowLayout/IGListkitViewController.m |
Delegation Flow
When the layout needs configuration values, SQCollectionRoundFlowLayout queries the IGListAdapter to locate the section controller owning that section index. If the controller implements the required JJCollectionViewDelegateRoundFlowLayout method, the layout uses that value; otherwise, it returns sensible defaults like UIEdgeInsetsZero.
Step-by-Step Integration Guide
Installing the Dependency
Add the pod to your Podfile and run pod install:
pod 'JJCollectionViewRoundFlowLayout'
Setting Up the Adapter and Layout
Create an IGListAdapter and instantiate SQCollectionRoundFlowLayout with that adapter. The wrapper stores a weak reference to route delegate calls.
// Create the IGListAdapter
self.adapter = [[IGListAdapter alloc] initWithUpdater:IGListAdapterUpdater.new
viewController:self
workingRangeSize:2];
// Initialize the wrapper layout with the adapter
SQCollectionRoundFlowLayout *layout = [[SQCollectionRoundFlowLayout alloc]
initWithIGListAdapter:self.adapter];
// Create the collection view
IGListCollectionView *collectionView = [[IGListCollectionView alloc]
initWithFrame:self.view.bounds
collectionViewLayout:layout];
collectionView.translatesAutoresizingMaskIntoConstraints = NO;
collectionView.backgroundColor = UIColor.whiteColor;
// Connect adapter to collection view
self.adapter.collectionView = collectionView;
self.adapter.dataSource = self;
Implementing the Section Controller
Create a subclass of IGListSectionController that adopts JJCollectionViewDelegateRoundFlowLayout. Implement the optional methods to customize the rounded background, shadows, and alignment for that specific section.
@interface MyIGListSectionController : IGListSectionController
<IGListSectionType,
JJCollectionViewDelegateRoundFlowLayout>
@end
@implementation MyIGListSectionController
- (NSInteger)numberOfItems {
return 5;
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)layout
borderEdgeInsertsForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsMake(8.f, 10.f, 8.f, 10.f);
}
- (JJCollectionViewRoundConfigModel *)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)layout
configModelForSectionAtIndex:(NSInteger)section {
JJCollectionViewRoundConfigModel *model = [[JJCollectionViewRoundConfigModel alloc] init];
model.cornerRadius = (section == 2) ? 0.f : 10.f;
model.backgroundColor = UIColor.whiteColor;
model.shadowColor = [UIColor colorWithRed:204/255.0 green:204/255.0 blue:204/255.0 alpha:0.6];
model.shadowOffset = CGSizeZero;
model.shadowOpacity = 1.f;
model.shadowRadius = 4.f;
return model;
}
- (JJCollectionViewRoundFlowLayoutAlignmentType)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)layout
alignmentTypeAtSection:(NSInteger)section {
return JJCollectionViewRoundFlowLayoutAlignmentTypeLeft;
}
- (UICollectionViewCell *)cellForItemAtIndex:(NSInteger)index {
UICollectionViewCell *cell = [self.collectionContext
dequeueReusableCellOfClass:UICollectionViewCell.class
forSectionController:self
atIndex:index];
cell.backgroundColor = (index % 2 == 0) ? UIColor.redColor : UIColor.orangeColor;
return cell;
}
@end
Return this section controller from your IGListAdapterDataSource implementation:
- (IGListSectionController<IGListSectionType> *)listAdapter:(IGListAdapter *)listAdapter
sectionControllerForObject:(id)object {
MyIGListSectionController *controller = [[MyIGListSectionController alloc] init];
controller.inset = UIEdgeInsetsMake(40.f, 20.f, 40.f, 20.f);
controller.minimumLineSpacing = 10.f;
controller.minimumInteritemSpacing = 5.f;
return controller;
}
Complete Implementation Example
The following view controller demonstrates the full wiring between IGListKit and the rounded layout, including adapter setup, layout initialization, and data source methods.
// IGListkitViewController.m
#import "IGListkitViewController.h"
#import <IGListKit/IGListKit.h>
@import JJCollectionViewRoundFlowLayout;
#import "SQCollectionRoundFlowLayout.h"
#import "MyIGListSectionController.h"
@interface IGListkitViewController () <IGListAdapterDataSource, IGListAdapterDelegate>
@property (strong, nonatomic) IGListCollectionView *collectionView;
@property (nonatomic, strong) IGListAdapter *adapter;
@end
@implementation IGListkitViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self setupAdapterAndLayout];
[self layoutCollectionView];
}
- (void)setupAdapterAndLayout {
self.adapter = [[IGListAdapter alloc] initWithUpdater:IGListAdapterUpdater.new
viewController:self
workingRangeSize:2];
SQCollectionRoundFlowLayout *layout = [[SQCollectionRoundFlowLayout alloc]
initWithIGListAdapter:self.adapter];
self.collectionView = [[IGListCollectionView alloc]
initWithFrame:self.view.bounds
collectionViewLayout:layout];
self.collectionView.translatesAutoresizingMaskIntoConstraints = NO;
self.collectionView.backgroundColor = UIColor.whiteColor;
self.adapter.collectionView = self.collectionView;
self.adapter.dataSource = self;
self.adapter.delegate = self;
[self.view addSubview:self.collectionView];
}
- (void)layoutCollectionView {
UIView *cv = self.collectionView;
UIView *parent = self.view;
[parent addConstraints:@[
[NSLayoutConstraint constraintWithItem:cv attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:parent attribute:NSLayoutAttributeTop multiplier:1 constant:0],
[NSLayoutConstraint constraintWithItem:cv attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationEqual
toItem:parent attribute:NSLayoutAttributeLeft multiplier:1 constant:0],
[NSLayoutConstraint constraintWithItem:cv attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:parent attribute:NSLayoutAttributeBottom multiplier:1 constant:0],
[NSLayoutConstraint constraintWithItem:cv attribute:NSLayoutAttributeRight
relatedBy:NSLayoutRelationEqual
toItem:parent attribute:NSLayoutAttributeRight multiplier:1 constant:0],
]];
}
#pragma mark - IGListAdapterDataSource
- (NSArray<id<IGListDiffable>> *)objectsForListAdapter:(IGListAdapter *)listAdapter {
return @[@"1", @"2", @"3", @"4", @"5", @"6", @"7"];
}
- (IGListSectionController<IGListSectionType> *)listAdapter:(IGListAdapter *)listAdapter
sectionControllerForObject:(id)object {
MyIGListSectionController *controller = [[MyIGListSectionController alloc] init];
controller.inset = UIEdgeInsetsMake(40.f, 20.f, 40.f, 20.f);
controller.minimumLineSpacing = 10.f;
controller.minimumInteritemSpacing = 5.f;
return controller;
}
- (UIView *)emptyViewForListAdapter:(IGListAdapter *)listAdapter {
return nil;
}
@end
Key Source Files and Responsibilities
Understanding these specific files in the kingjiajie/jjcollectionviewroundflowlayout repository helps you customize the integration:
-
JJCollectionViewRoundFlowLayout/Classes/JJCollectionViewRoundFlowLayout.h— Defines the coreJJCollectionViewRoundFlowLayoutclass and theJJCollectionViewDelegateRoundFlowLayoutprotocol with methods likeconfigModelForSectionAtIndex:andborderEdgeInsertsForSectionAtIndex:. -
JJCollectionViewRoundFlowLayout/Classes/JJCollectionViewRoundConfigModel.h— Contains the model class holding visual properties:cornerRadius,backgroundColor,shadowColor,shadowOpacity,shadowRadius, and border settings. -
Example/JJCollectionViewRoundFlowLayout/SQCollectionRoundFlowLayout.m— Implements the forwarding logic in methods likecollectionView:layout:configModelForSectionAtIndex:by querying the adapter via[_adapter sectionControllerForObject:[_adapter objectAtSection:section]]and forwarding to the controller if it responds to the selector. -
Example/JJCollectionViewRoundFlowLayout/IGListkitViewController.m— Reference implementation showing how to wire the adapter, layout, and data source together in a production view controller.
Summary
-
Use
SQCollectionRoundFlowLayoutas a drop-in replacement forJJCollectionViewRoundFlowLayoutwhen working with IGListKit; it handles all delegate forwarding automatically. -
Initialize with the adapter by calling
initWithIGListAdapter:to establish the forwarding chain. -
Implement
JJCollectionViewDelegateRoundFlowLayoutin yourIGListSectionControllersubclasses to control corner radius, background color, shadows, and border insets per section. -
Return configuration models via
configModelForSectionAtIndex:to customize the visual appearance without breaking IGListKit's data-driven architecture. -
Reference the example files in the repository's
Example/directory for complete working implementations of the wrapper and view controller setup.
Frequently Asked Questions
How does SQCollectionRoundFlowLayout handle delegate methods without a traditional collection view delegate?
SQCollectionRoundFlowLayout overrides the delegate getter to return self, then implements each JJCollectionViewDelegateRoundFlowLayout method by querying the IGListAdapter for the section controller at the specified index. According to the source in SQCollectionRoundFlowLayout.m, it calls [_adapter sectionControllerForObject:[_adapter objectAtSection:section]] and checks if the returned controller responds to the delegate method using respondsToSelector: before forwarding the call.
Can I use different corner radii for different sections in the same collection view?
Yes. Because the layout queries the section controller for each index via configModelForSectionAtIndex:, you can return different JJCollectionViewRoundConfigModel instances with varying cornerRadius values. In your IGListSectionController implementation, inspect the section parameter or instance variables to determine the appropriate radius, as shown in the example where model.cornerRadius is set conditionally based on the section index.
What happens if my section controller does not implement a specific delegate method?
The wrapper provides safe defaults. In SQCollectionRoundFlowLayout.m, methods like borderEdgeInsertsForSectionAtIndex: return UIEdgeInsetsZero and alignmentTypeAtSection: returns the default alignment if the section controller does not implement the protocol method. This ensures the layout functions correctly even with partial protocol adoption.
Do I need to set the collection view's delegate property manually when using this integration?
No. You should not set collectionView.delegate manually because IGListAdapter manages the delegate and data source. The SQCollectionRoundFlowLayout acts as its own delegate internally and forwards specific rounded-layout queries to your section controllers, allowing the adapter to maintain control over the standard collection view delegate pattern.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →