How to Customize Cell Alignment for Specific Sections Using Delegates in JJCollectionViewRoundFlowLayout

JJCollectionViewRoundFlowLayout supports per-section cell alignment through the JJCollectionViewDelegateRoundFlowLayout protocol, allowing you to override the global collectionCellAlignmentType setting for individual sections by implementing collectionView:layout:alignmentTypeAtSection:.

JJCollectionViewRoundFlowLayout extends UICollectionViewFlowLayout to provide rounded section backgrounds and flexible cell alignment options. When building complex collection views with heterogeneous sections, you often need different horizontal alignments for different sections—some left-aligned, others centered or right-aligned. This library solves that problem through a delegate-based approach that queries alignment preferences on a per-section basis during the layout calculation cycle.

Understanding Global vs. Per-Section Alignment Scope

The library provides two distinct scopes for controlling horizontal cell alignment in vertical-scrolling collection views:

  • Global alignment: Set the collectionCellAlignmentType property on the layout object. This applies uniformly to all sections unless overridden.
  • Per-section alignment: Implement the delegate method collectionView:layout:alignmentTypeAtSection:. The layout queries this method for each section during layoutAttributesForElementsInRect:, falling back to the global setting if the delegate does not implement the selector.

By default, the layout uses JJCollectionViewFlowLayoutAlignmentTypeBySystem, which defers to the standard UIKit behavior.

How the Delegate Consultation Works

During the layout calculation in JJCollectionViewRoundFlowLayout.m (lines 556–562), the layout checks whether the delegate responds to the alignment selector:

id delegate = self.collectionView.delegate;
if ([delegate respondsToSelector:@selector(collectionView:layout:alignmentTypeAtSection:)]) {
    // Delegate will provide per-section alignment
}

If the method is present, the layout groups attributes by section using groupLayoutAttributesForElementsBySectionWithLayoutAttributesAttrs:, then processes each group through analysisCellSettingFrameWithLayoutAttributesAttrs:toChangeAttributesAttrsList:cellAlignmentType:. The actual frame adjustments for left, center, and right alignment are implemented in the JJCollectionViewRoundFlowLayout+Alignment category methods (evaluatedCellSettingFrameByLeft…, …Center…, …Right…).

Available Alignment Types

The alignment behavior is controlled by the JJCollectionViewRoundFlowLayoutAlignmentType enum defined in JJCollectionViewFlowLayoutConfig.h (lines 11–17):

typedef enum : NSUInteger {
    JJCollectionViewFlowLayoutAlignmentTypeBySystem = 0,
    JJCollectionViewFlowLayoutAlignmentTypeByLeft,
    JJCollectionViewFlowLayoutAlignmentTypeByCenter,
    JJCollectionViewFlowLayoutAlignmentTypeByRight,
    JJCollectionViewFlowLayoutAlignmentTypeByRightAndStartR,
} JJCollectionViewRoundFlowLayoutAlignmentType;
  • BySystem: Uses standard UICollectionViewFlowLayout behavior
  • ByLeft: Aligns cells to the left edge of the section
  • ByCenter: Centers cells within the section
  • ByRight: Aligns cells to the right edge
  • ByRightAndStartR: Right alignment with RTL (Right-to-Left) layout support

Implementing Per-Section Alignment

Basic Setup via Collection View Delegate

The simplest approach uses your view controller as the delegate. Ensure your class conforms to JJCollectionViewDelegateRoundFlowLayout and implement the alignment method:

@interface MyViewController () <JJCollectionViewDelegateRoundFlowLayout>
@end

@implementation MyViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    JJCollectionViewRoundFlowLayout *flow = [[JJCollectionViewRoundFlowLayout alloc] init];
    flow.scrollDirection = UICollectionViewScrollDirectionVertical;
    
    UICollectionView *cv = [[UICollectionView alloc] initWithFrame:self.view.bounds
                                            collectionViewLayout:flow];
    cv.delegate = self;  // Critical: sets the alignment delegate
    cv.dataSource = self;
    [self.view addSubview:cv];
}

#pragma mark - JJCollectionViewDelegateRoundFlowLayout

- (JJCollectionViewRoundFlowLayoutAlignmentType)collectionView:(UICollectionView *)collectionView
                                                       layout:(UICollectionViewLayout *)layout
                                         alignmentTypeAtSection:(NSInteger)section {
    // Example: Even sections centered, odd sections left-aligned
    return (section % 2 == 0)
           ? JJCollectionViewFlowLayoutAlignmentTypeByCenter
           : JJCollectionViewFlowLayoutAlignmentTypeByLeft;
}
@end

The delegate method declaration resides in JJCollectionViewRoundFlowLayout.h (lines 47–53).

Using a Separate Delegate Object

For better separation of concerns, assign a dedicated delegate to the layout's delegate property:

// AlignmentProvider.h
@interface AlignmentProvider : NSObject <JJCollectionViewDelegateRoundFlowLayout>
@end

// AlignmentProvider.m
@implementation AlignmentProvider
- (JJCollectionViewRoundFlowLayoutAlignmentType)collectionView:(UICollectionView *)c
                                                       layout:(UICollectionViewLayout *)l
                                         alignmentTypeAtSection:(NSInteger)s {
    return (s == 2) ? JJCollectionViewFlowLayoutAlignmentTypeByRight 
                    : JJCollectionViewFlowLayoutAlignmentTypeByCenter;
}
@end

// Configuration
JJCollectionViewRoundFlowLayout *layout = [[JJCollectionViewRoundFlowLayout alloc] init];
AlignmentProvider *provider = [AlignmentProvider new];
layout.delegate = provider;  // Custom delegate separate from collectionView.delegate

Fallback to Global Settings

If you need uniform alignment without per-section logic, set the global property and omit the delegate method:

JJCollectionViewRoundFlowLayout *layout = [[JJCollectionViewRoundFlowLayout alloc] init];
layout.collectionCellAlignmentType = JJCollectionViewFlowLayoutAlignmentTypeByRight;
// All sections align right; no delegate implementation required

Summary

  • JJCollectionViewRoundFlowLayout queries the delegate method collectionView:layout:alignmentTypeAtSection: for each section during layout calculations in JJCollectionViewRoundFlowLayout.m.
  • The layout supports five alignment types defined in JJCollectionViewFlowLayoutConfig.h: System, Left, Center, Right, and RightAndStartR.
  • You can use the collection view's delegate or assign a separate delegate object via the delegate property.
  • If the delegate does not implement the alignment method, the layout falls back to the collectionCellAlignmentType property value.
  • Frame calculations are handled by the JJCollectionViewRoundFlowLayout+Alignment category methods.

Frequently Asked Questions

What happens if I don't implement the delegate method?

If the delegate does not respond to collectionView:layout:alignmentTypeAtSection:, the layout uses the global collectionCellAlignmentType property for that section. If no global type is set, it defaults to JJCollectionViewFlowLayoutAlignmentTypeBySystem.

Can I use a different delegate than the collection view's delegate?

Yes. While the layout automatically checks self.collectionView.delegate first, you can assign a separate object conforming to JJCollectionViewDelegateRoundFlowLayout to the layout's delegate property. This is useful when you want to isolate layout logic from your view controller.

Which alignment type should I use for right-aligned layouts with RTL support?

Use JJCollectionViewFlowLayoutAlignmentTypeByRightAndStartR instead of ByRight. This enum value ensures proper behavior in Right-to-Left language environments by respecting the layout direction, whereas ByRight applies a fixed right alignment regardless of locale.

Where does the actual frame calculation happen?

The frame adjustments occur in JJCollectionViewRoundFlowLayout+Alignment through helper methods like evaluatedCellSettingFrameByLeftWith…, …ByCenter…, and …ByRight…. These are called from analysisCellSettingFrameWithLayoutAttributesAttrs:toChangeAttributesAttrsList:cellAlignmentType: after the delegate provides the alignment type for the section.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →