# Supporting Vertical and Horizontal Scrolling with Rounded Section Layouts in iOS

> Implement rounded section layouts with vertical and horizontal scrolling in iOS. JJCollectionViewRoundFlowLayout automatically adapts for seamless UI.

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

---

**`JJCollectionViewRoundFlowLayout` automatically adapts its rounded background decoration to both vertical and horizontal scrolling by calculating section frames relative to the current `scrollDirection` property.**

`JJCollectionViewRoundFlowLayout` is a drop-in replacement for `UICollectionViewFlowLayout` that draws rounded section backgrounds using decoration views. The layout engine detects whether the collection view scrolls vertically or horizontally and adjusts all size and position calculations accordingly, making it straightforward to implement rounded section layouts in any orientation.

## How Scroll Direction Affects Section Frame Calculations

The layout determines the scrolling axis by reading `self.scrollDirection` inherited from `UICollectionViewFlowLayout`. In `prepareLayout`, the code builds `sectionFrame` using a conditional that expands the background either across the width (vertical scrolling) or height (horizontal scrolling):

```objc
sectionFrame = self.scrollDirection == UICollectionViewScrollDirectionVertical ?
    CGRectMake(rect.origin.x, rect.origin.y, self.collectionView.bounds.size.width, rect.size.height) :
    CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, self.collectionView.bounds.size.height);

```

This logic appears in `JJCollectionViewRoundFlowLayout.m` (lines 34-36) and ensures the rounded background always stretches across the full scrollable axis. The same conditional pattern appears in `calculateDefaultFrameWithSectionFrame:sectionInset:` (lines 29-45) to handle fallback frames when sections lack headers or footers.

## Core Architecture and Key Components

### JJCollectionViewRoundFlowLayout

The main layout subclass drives the layout pass, creates decoration-view attributes, and adjusts frames for headers, footers, and insets. The implementation in `JJCollectionViewRoundFlowLayout.m` (lines 79-84, 99-110) handles the core geometry calculations.

### JJCollectionViewRoundLayoutAttributes

Custom layout attributes carry the background configuration model, border insets, and optional touch-animation settings. Defined in `JJCollectionViewRoundFlowLayout.m` (lines 15-22), these attributes pass styling data to the decoration view during the layout pass.

### JJCollectionReusableView

The decoration view renders the rounded background, shadow, border, and optional background image. It updates its layer when trait collections change to support dark mode. The rendering logic lives in `toChangeCollectionReusableViewRoundInfoWithLayoutAttributes:` (lines 85-140 of `JJCollectionViewRoundFlowLayout.m`).

### Delegate Protocol (JJCollectionViewDelegateRoundFlowLayout)

The protocol allows view controllers to supply per-section configuration models, custom border insets, and control header/footer inclusion. Defined in [`JJCollectionViewRoundFlowLayout.h`](https://github.com/kingjiajie/jjcollectionviewroundflowlayout/blob/main/JJCollectionViewRoundFlowLayout.h) (lines 16-66), key methods include:

- `configModelForSectionAtIndex:` – Returns `JJCollectionViewRoundConfigModel` with colors, radius, and shadows.
- `borderEdgeInsertsForSectionAtIndex:` – Returns `UIEdgeInsets` for the background border, independent of `sectionInset`.
- `animationConfigModelForSection:` – Optional touch-animation configuration.

## Implementing Vertical Scrolling with Rounded Backgrounds

Vertical scrolling is the default behavior. Initialize the layout and assign it to your collection view:

```objc
JJCollectionViewRoundFlowLayout *layout = [[JJCollectionViewRoundFlowLayout alloc] init];
UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds
                                                     collectionViewLayout:layout];
collectionView.delegate   = self;
collectionView.dataSource = self;
[self.view addSubview:collectionView];

```

The layout automatically calculates `sectionFrame` using the full width of the collection view bounds, as shown in the conditional logic in `prepareLayout` (lines 34-36). For a complete working example, see `SecondViewController.m` in the repository's Example target (lines 30-34 for layout setup, lines 39-68 for delegate implementation).

## Implementing Horizontal Scrolling with Rounded Backgrounds

To switch to horizontal scrolling, set the `scrollDirection` property before initializing the collection view:

```objc
JJCollectionViewRoundFlowLayout *layout = [[JJCollectionViewRoundFlowLayout alloc] init];
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;   // Key configuration
UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds
                                                     collectionViewLayout:layout];

```

When `scrollDirection` is set to horizontal, the layout adjusts `sectionFrame` to use the full height of the collection view bounds while allowing the width to expand based on cell content (see the ternary operator in `prepareLayout`). The repository's `ThirdViewController.m` demonstrates this configuration.

## Customizing Section Appearance

### Background Colors, Shadows, and Corner Radius

Implement the delegate method `configModelForSectionAtIndex:` to return a `JJCollectionViewRoundConfigModel` instance:

```objc
- (JJCollectionViewRoundConfigModel *)collectionView:(UICollectionView *)cv
                      layout:(UICollectionViewLayout *)layout
   configModelForSectionAtIndex:(NSInteger)section {
    JJCollectionViewRoundConfigModel *model = [[JJCollectionViewRoundConfigModel alloc] init];
    model.backgroundColor = [UIColor systemBackgroundColor];
    model.cornerRadius = 12.0;
    model.shadowColor   = [UIColor blackColor];
    model.shadowOpacity = 0.15;
    model.shadowRadius  = 6.0;
    model.shadowOffset  = CGSizeMake(0, 2);
    return model;
}

```

### Border Insets Independent of Section Insets

To add padding between the rounded background and the section edges without affecting cell positioning, implement `borderEdgeInsertsForSectionAtIndex:`:

```objc
- (UIEdgeInsets)collectionView:(UICollectionView *)cv
                         layout:(UICollectionViewLayout *)layout
       borderEdgeInsertsForSectionAtIndex:(NSInteger)section {
    return UIEdgeInsetsMake(8, 16, 8, 16);
}

```

These insets are applied to the decoration view frame after the main `sectionFrame` calculation (see lines 80-84 of `layoutAttributesForElementsInRect:` in `JJCollectionViewRoundFlowLayout.m`).

### Optional Touch Animations

Enable tap feedback on the rounded background:

```objc
layout.isDecorationViewTouchAnimationEnable = YES;

```

Configure per-section animation behavior:

```objc
- (JJCollectionViewTouchAnimationConfigModel *)collectionView:(UICollectionView *)cv
                       layout:(UICollectionViewLayout *)layout
   animationConfigModelForSection:(NSInteger)section {
    JJCollectionViewTouchAnimationConfigModel *anim = [JJCollectionViewTouchAnimationConfigModel createDefaultModel];
    anim.scale = 0.95;
    anim.duration = 0.2;
    return anim;
}

```

Touch handling is implemented in `JJCollectionReusableView` via `touchesBegan:` and `touchesEnded:` methods.

## Summary

- `JJCollectionViewRoundFlowLayout` is a drop-in replacement for `UICollectionViewFlowLayout` that adds rounded background decoration views to collection view sections.
- The layout automatically supports both **vertical and horizontal scrolling** by checking `self.scrollDirection` and adjusting `sectionFrame` calculations to stretch across the appropriate axis.
- All styling (colors, shadows, corner radius) is configured via the `JJCollectionViewDelegateRoundFlowLayout` protocol using `JJCollectionViewRoundConfigModel`.
- Border insets can be specified independently of the collection view's `sectionInset` through `borderEdgeInsertsForSectionAtIndex:`.
- Optional touch animations are available by setting `isDecorationViewTouchAnimationEnable` and implementing `animationConfigModelForSection:`.

## Frequently Asked Questions

### Does `JJCollectionViewRoundFlowLayout` support both vertical and horizontal layouts simultaneously?

No, the layout respects the single `scrollDirection` property inherited from `UICollectionViewFlowLayout`. You must set `layout.scrollDirection` to either `UICollectionViewScrollDirectionVertical` or `UICollectionViewScrollDirectionHorizontal`. The layout calculations in `prepareLayout` (lines 34-36 of `JJCollectionViewRoundFlowLayout.m`) use a ternary operator to adjust the `sectionFrame` based on this property, ensuring the rounded background stretches across the correct axis.

### How do I change the corner radius for specific sections only?

Implement the delegate method `configModelForSectionAtIndex:` and return a `JJCollectionViewRoundConfigModel` with the desired `cornerRadius` value for that section. For example, return a model with `cornerRadius = 12.0` for section 0 and `cornerRadius = 20.0` for section 1. The layout attributes will carry this configuration to the `JJCollectionReusableView` decoration view, which applies the corner radius to its layer in `toChangeCollectionReusableViewRoundInfoWithLayoutAttributes:`.

### Can I use this layout with self-sizing cells?

Yes, `JJCollectionViewRoundFlowLayout` inherits from `UICollectionViewFlowLayout` and respects the `estimatedItemSize` property for self-sizing cells. The layout calculates the `sectionFrame` based on the actual frames of the first and last cells in each section (see `prepareLayout` lines 79-110), so it automatically adapts to dynamic cell sizes. Ensure your delegate methods return appropriate config models regardless of cell size changes.

### Where is the decoration view rendering implemented?

The rounded background decoration view is implemented in the `JJCollectionReusableView` class found within `JJCollectionViewRoundFlowLayout.m` (lines 85-140). This class overrides `applyLayoutAttributes:` to receive the `JJCollectionViewRoundLayoutAttributes` containing the configuration model. The method `toChangeCollectionReusableViewRoundInfoWithLayoutAttributes:` handles the actual Core Layer rendering of the background color, corner radius, shadow, border, and optional background image. The view also responds to trait collection changes to support dark mode updates.