# JJCollectionViewRoundFlowLayout Custom Section Header and Footer Calculation

> Learn JJCollectionViewRoundFlowLayout custom section header and footer calculation. Discover how it merges attributes and frames with custom insets for rounded background decoration views.

- Repository: [Kingjiajie_Go/jjcollectionviewroundflowlayout](https://github.com/kingjiajie/jjcollectionviewroundflowlayout)
- Tags: how-to-guide
- Published: 2026-03-05

---

**JJCollectionViewRoundFlowLayout calculates section header and footer frames by querying supplementary view attributes, merging them with cell frames using CGRectUnion, and applying custom border insets to generate rounded background decoration views.**

The `kingjiajie/jjcollectionviewroundflowlayout` repository extends `UICollectionViewFlowLayout` to draw rounded backgrounds behind collection view sections. Understanding **JJCollectionViewRoundFlowLayout custom section header and footer calculation** is essential for creating polished section backgrounds that properly encompass headers, footers, and cells while handling edge cases like empty sections and irregular cell sizes.

## How Header and Footer Frames Are Calculated

### Collecting Section Information

In `JJCollectionViewRoundFlowLayout.m`, the `‑prepareLayout` method iterates over every section using a standard `for` loop: `for (NSInteger section = 0; section < sections; section++)`. For each section, the layout determines geometry by first obtaining the first and last item frames via `layoutAttributesForItemAtIndexPath:`. If the section is empty, the delegate method `collectionView:layout:isCanCalculateWhenRowEmptyWithSection:` (or the property `isCanCalculateWhenRowEmpty`) determines whether processing continues.

### Header Detection and Frame Calculation

The layout first evaluates the `isCalculateHeader` property. However, the delegate can override this per section:

```objc
BOOL isCalculateHeaderView = self.isCalculateHeader;
if ([delegate respondsToSelector:@selector(collectionView:layout:isCalculateHeaderViewIndex:)]) {
    isCalculateHeaderView = [delegate collectionView:self.collectionView layout:self isCalculateHeaderViewIndex:section];
}

```

When `isCalculateHeaderView` is `YES`, the layout fetches attributes via `layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader`. If a header exists, its frame becomes the `firstFrame`; otherwise, the layout uses the first cell's frame. For sections with irregularly sized cells, enabling `isCalculateTypeOpenIrregularitiesCell` triggers `calculateIrregularitiesCellByMinTopFrameWithLayout:` to ensure the background covers all cells regardless of size variations.

### Footer Detection and Frame Calculation

The footer follows an identical pattern using `isCalculateFooter`, `collectionView:layout:isCalculateFooterViewIndex:`, and `layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionFooter`. The resulting footer frame serves as the `lastFrame`, or the layout falls back to the last cell. When handling irregular layouts, `calculateIrregularitiesCellByMaxBottomFrameWithLayout:` expands the frame to include the bottom-most cells.

### Merging Frames and Applying Insets

The layout unites the header and footer frames using `CGRectUnion(firstFrame, lastFrame)` to create the section content rectangle. It then applies two types of insets:

- **Standard section insets** from `JJCollectionViewFlowLayoutUtils evaluatedSectionInsetForItemWithCollectionLayout:`
- **Custom border insets** provided by the delegate via `collectionView:layout:borderEdgeInsertsForSectionAtIndex:`

These insets are added to the calculated rectangle and stored in the decoration attributes' `borderEdgeInsets` property. The final `JJCollectionViewRoundLayoutAttributes` object receives the section frame, `zIndex` of -1 (to appear behind cells), and a `myConfigModel` instance containing visual styling parameters.

```objc
JJCollectionViewRoundLayoutAttributes *attr = [JJCollectionViewRoundLayoutAttributes
    layoutAttributesForDecorationViewOfKind:JJCollectionViewRoundSection
    withIndexPath:[NSIndexPath indexPathForRow:0 inSection:section]];
attr.frame = sectionFrame;
attr.zIndex = -1;
attr.borderEdgeInsets = userCustomSectionInset;
attr.myConfigModel = [delegate collectionView:self.collectionView layout:self configModelForSectionAtIndex:section];

```

## Implementing the Delegate Protocol

To customize header and footer calculation behavior, implement the `JJCollectionViewDelegateRoundFlowLayout` protocol defined in [`JJCollectionViewRoundFlowLayout.h`](https://github.com/kingjiajie/jjcollectionviewroundflowlayout/blob/main/JJCollectionViewRoundFlowLayout.h).

### Basic Setup

```objc
#import "JJCollectionViewRoundFlowLayout.h"

- (void)viewDidLoad {
    [super viewDidLoad];

    JJCollectionViewRoundFlowLayout *layout = [JJCollectionViewRoundFlowLayout new];
    layout.isRoundEnabled = YES;
    layout.isCalculateHeader = YES;
    layout.isCalculateFooter = YES;
    layout.delegate = self;
    self.collectionView.collectionViewLayout = layout;
}

```

### Controlling Header and Footer Backgrounds

Override default calculation flags for specific sections:

```objc
- (BOOL)collectionView:(UICollectionView *)collectionView
               layout:(UICollectionViewLayout *)collectionViewLayout
isCalculateHeaderViewIndex:(NSInteger)section {
    // Only even-indexed sections calculate header backgrounds
    return (section % 2 == 0);
}

- (BOOL)collectionView:(UICollectionView *)collectionView
               layout:(UICollectionViewLayout *)collectionViewLayout
isCalculateFooterViewIndex:(NSInteger)section {
    return YES;
}

```

### Providing Visual Configuration

Supply styling and custom border insets:

```objc
- (JJCollectionViewRoundConfigModel *)collectionView:(UICollectionView *)collectionView
                                            layout:(UICollectionViewLayout *)collectionViewLayout
                         configModelForSectionAtIndex:(NSInteger)section {
    JJCollectionViewRoundConfigModel *model = [JJCollectionViewRoundConfigModel new];
    model.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0];
    model.cornerRadius = 12.0;
    model.borderWidth = 1.0;
    model.borderColor = [UIColor lightGrayColor];
    model.shadowColor = [UIColor blackColor];
    model.shadowOpacity = 0.2;
    model.shadowRadius = 4.0;
    return model;
}

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView
                        layout:(UICollectionViewLayout *)collectionViewLayout
            borderEdgeInsertsForSectionAtIndex:(NSInteger)section {
    return UIEdgeInsetsMake(5, 10, 5, 10);
}

```

## Handling Edge Cases

### Empty Sections

When a section contains no items, the layout checks the `isCanCalculateWhenRowEmpty` property or delegates to `collectionView:layout:isCanCalculateWhenRowEmptyWithSection:`. If enabled, the layout calculates the background based solely on the header and footer frames, or the section's theoretical bounds if neither supplementary view exists.

### Irregular Cell Sizes

For flow layouts with variable cell heights, enabling `isCalculateTypeOpenIrregularitiesCell` ensures the rounded background encompasses all cells regardless of their vertical position. The layout calls `calculateIrregularitiesCellByMinTopFrameWithLayout:` and `calculateIrregularitiesCellByMaxBottomFrameWithLayout:` in `JJCollectionViewFlowLayoutUtils` to determine the true bounds.

### Touch Animations

If `isDecorationViewTouchAnimationEnable` is set, or if the delegate implements `collectionView:layout:isDecorationViewShowAnimationAtIndex:`, the decoration view receives a `JJCollectionViewTouchAnimationConfigModel`. The internal `JJCollectionReusableView` class handles tap gestures, applying scale transforms to both the background and the cells within that section.

## Summary

- **Frame Calculation**: The layout merges header, footer, and cell frames using `CGRectUnion` in `JJCollectionViewRoundFlowLayout.m` to determine total section bounds.
- **Delegate Control**: Implement `isCalculateHeaderViewIndex:` and `isCalculateFooterViewIndex:` to selectively enable backgrounds per section, overriding the default `isCalculateHeader` and `isCalculateFooter` properties.
- **Inset Configuration**: Use `borderEdgeInsertsForSectionAtIndex:` to specify spacing between the rounded background and section content, separate from standard `sectionInset`.
- **Edge Case Handling**: Empty sections and irregular cell layouts are supported through dedicated delegate methods and calculation utilities in `JJCollectionViewFlowLayoutUtils`.
- **Visual Customization**: The `JJCollectionViewRoundConfigModel` provides comprehensive styling options including corner radius, shadows, borders, and background colors rendered by `JJCollectionReusableView`.

## Frequently Asked Questions

### How do I disable header background calculation for specific sections?

Implement the `collectionView:layout:isCalculateHeaderViewIndex:` delegate method. Return `NO` for sections that should not display a background behind their headers. The layout defaults to the `isCalculateHeader` property value when the delegate method is not implemented.

### What happens if a section has no items but I still want a rounded background?

Set the `isCanCalculateWhenRowEmpty` property to `YES` or implement `collectionView:layout:isCanCalculateWhenRowEmptyWithSection:` and return `YES` for the specific section. The layout will then calculate the background frame using only the header and footer attributes, or the section's theoretical bounds if neither exists.

### How do custom border insets differ from standard section insets?

**Border insets** are specific to the rounded background decoration and are supplied via `collectionView:layout:borderEdgeInsertsForSectionAtIndex:`. They control the spacing between the edge of the rounded background and the content. **Section insets** (`sectionInset`) control the spacing between cells and the collection view boundaries. The layout applies both in `JJCollectionViewRoundFlowLayout.m` when calculating the final decoration view frame.

### Can I animate the rounded background when the user taps on it?

Yes. Enable `isDecorationViewTouchAnimationEnable` on the layout, or implement `collectionView:layout:isDecorationViewShowAnimationAtIndex:` to enable animations for specific sections. The internal `JJCollectionReusableView` class handles touch events and applies scale animations using `JJCollectionViewTouchAnimationConfigModel` settings. If you don't provide a custom animation configuration, the layout uses default values from the model class.