How JJCollectionViewRoundFlowLayout Handles Empty Cells: Delegate and Property Configuration
JJCollectionViewRoundFlowLayout skips round background decoration for empty sections by default, but provides granular control through the delegate method collectionView:layout:isCanCalculateWhenRowEmptyWithSection: or the Boolean property isCanCalculateWhenRowEmpty.
JJCollectionViewRoundFlowLayout is an open-source iOS library that adds rounded background decoration to UICollectionView sections. When sections contain no cells, the layout must decide whether to render the background decoration anyway. According to the kingjiajie/jjcollectionviewroundflowlayout repository, the library implements a two-tiered decision system in prepareLayout that checks a delegate method first, then falls back to a configuration property.
The Two-Step Empty Section Detection Mechanism
The layout determines whether to draw a round background for a section containing zero items through a prioritized two-step mechanism. This design allows developers to override behavior globally via properties or dynamically via delegate callbacks.
Step 1: Delegate Method Control
If the layout’s delegate implements the optional protocol method, the layout delegates the decision entirely to this method:
- (BOOL)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
isCanCalculateWhenRowEmptyWithSection:(NSInteger)section;
When the delegate returns NO, the section is skipped and no decoration view is created. Returning YES forces the layout to treat the empty section like a normal one, computing a background view based on any existing header or footer.
Step 2: Property Fallback
If the delegate does not implement the method, the layout falls back to the Boolean property isCanCalculateWhenRowEmpty. When this property is NO (the default), empty sections are skipped. Setting the property to YES forces background calculation for all empty sections globally.
Implementation Details in prepareLayout
The relevant logic lives in prepareLayout within JJCollectionViewRoundFlowLayout.m. The layout iterates through sections and applies the two-step check before creating decoration attributes.
The detection and skipping logic appears around lines 998-1005:
if (numberOfItems > 0) {
// normal case – obtain first item frame …
} else if ([delegate respondsToSelector:@selector(collectionView:layout:isCanCalculateWhenRowEmptyWithSection:)]) {
// delegate decides whether to calculate the background for an empty section
if (![delegate collectionView:self.collectionView
layout:self
isCanCalculateWhenRowEmptyWithSection:section]) {
continue; // skip this section
}
} else if (!self.isCanCalculateWhenRowEmpty) {
// no delegate, fall back to the property flag
continue; // skip this section
}
When the continue statement executes, the layout does not create a JJCollectionViewRoundLayoutAttributes object for that section, preventing any decoration view from entering the collection view hierarchy.
If the section passes the empty-section check, the layout proceeds to compute sectionFrame, optionally merging header and footer frames, applying borderEdgeInsets, and finally appending a decoration attribute:
JJCollectionViewRoundLayoutAttributes *attr =
[JJCollectionViewRoundLayoutAttributes layoutAttributesForDecorationViewOfKind:JJCollectionViewRoundSection
withIndexPath:[NSIndexPath indexPathForRow:0 inSection:section]];
attr.frame = sectionFrame;
attr.zIndex = -1;
// … configure config model, touch-animation, etc.
[self.decorationViewAttrs addObject:attr];
Configuration Outcomes Matrix
The interaction between the delegate method and the fallback property produces four distinct behaviors:
| Delegate Implementation | Return Value / Property State | Result for Empty Sections |
|---|---|---|
| Implements method | Returns NO |
Section is ignored; no background drawn. |
| Implements method | Returns YES |
Section is processed; background drawn based on header/footer or default frame. |
| Does not implement | isCanCalculateWhenRowEmpty = NO (default) |
Section is ignored. |
| Does not implement | isCanCalculateWhenRowEmpty = YES |
Section is processed; background drawn. |
Practical Code Examples
Enabling Background for Empty Sections via Property
To globally allow background decoration for all empty sections without implementing delegate methods:
JJCollectionViewRoundFlowLayout *layout = [[JJCollectionViewRoundFlowLayout alloc] init];
layout.isCanCalculateWhenRowEmpty = YES; // treat empty sections like normal ones
collectionView.collectionViewLayout = layout;
Controlling Empty Section Handling with Delegate
For dynamic, per-section control, implement the delegate protocol:
@interface MyViewController () <JJCollectionViewDelegateRoundFlowLayout>
@end
@implementation MyViewController
- (BOOL)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)layout
isCanCalculateWhenRowEmptyWithSection:(NSInteger)section {
// Only draw backgrounds for even-indexed sections when they are empty
return (section % 2 == 0);
}
@end
Full Setup with Headers and Footers
When empty sections contain headers or footers, ensure the layout calculates their frames to determine the background bounds:
JJCollectionViewRoundFlowLayout *layout = [[JJCollectionViewRoundFlowLayout alloc] init];
layout.isCanCalculateWhenRowEmpty = YES; // allow empty sections
layout.isCalculateHeader = YES; // honour header view
layout.isCalculateFooter = YES; // honour footer view
layout.delegate = self; // optional delegate for fine-grained control
collectionView.collectionViewLayout = layout;
Summary
- JJCollectionViewRoundFlowLayout skips decoration for empty sections by default to avoid rendering unnecessary backgrounds.
- Delegate priority: Implement
collectionView:layout:isCanCalculateWhenRowEmptyWithSection:to dynamically control empty section rendering per section. - Property fallback: Set
isCanCalculateWhenRowEmptytoYESfor global enablement when no delegate method exists. - Implementation location: The logic resides in
prepareLayoutinsideJJCollectionViewRoundFlowLayout.m, specifically around lines 998-1005. - Header/Footer support: When empty sections are processed, the layout still calculates backgrounds based on existing header and footer frames.
Frequently Asked Questions
What happens to the round background when a section has no cells?
By default, no background is drawn. The layout checks if the section contains zero items and skips creating the decoration view unless explicitly permitted via the delegate method collectionView:layout:isCanCalculateWhenRowEmptyWithSection: or the isCanCalculateWhenRowEmpty property set to YES.
Can I show a background for empty sections that contain only a header or footer?
Yes. When isCanCalculateWhenRowEmpty is enabled or the delegate permits the section, the layout calculates the sectionFrame by incorporating header and footer frames (if isCalculateHeader and isCalculateFooter are enabled). This ensures the round background surrounds the header or footer even when no cells exist.
Where is the empty section detection logic implemented?
The detection logic is implemented in the prepareLayout method of JJCollectionViewRoundFlowLayout.m, specifically around lines 998-1005. This code block checks numberOfItems, queries the delegate if implemented, or falls back to the isCanCalculateWhenRowEmpty property before deciding whether to continue (skip) or proceed with decoration attribute creation.
Should I use the delegate method or the property for controlling empty sections?
Use the delegate method collectionView:layout:isCanCalculateWhenRowEmptyWithSection: when you need per-section control (for example, only showing backgrounds for specific empty sections). Use the property isCanCalculateWhenRowEmpty when you want a global setting that applies to all empty sections uniformly without implementing delegate methods.
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 →