Enabling Touch Animations for JJCollectionViewRoundFlowLayout Decoration Views: Implementation Guide
To enable touch animations for decoration views in JJCollectionViewRoundFlowLayout, set the isDecorationViewTouchAnimationEnable property to YES on your layout instance, or implement the delegate methods isDecorationViewShowAnimationAtIndex: and animationConfigModelForSection: to control animations per section with custom scaling and duration parameters.
JJCollectionViewRoundFlowLayout is an iOS library that adds rounded background decoration views behind collection view sections. According to the source code in kingjiajie/jjcollectionviewroundflowlayout, these decoration views support a built-in touch animation system that scales the background (and optionally the cells) when the user interacts with them. This guide explains the complete animation pipeline and provides production-ready implementation patterns.
Understanding the Touch Animation Architecture
The touch animation system consists of three core components that work together to provide both global and per-section control.
isDecorationViewTouchAnimationEnable is a Boolean property defined in JJCollectionViewRoundFlowLayout.h that acts as a master switch. When set to YES, all decoration views in the collection view become eligible for touch animations using default parameters.
JJCollectionViewTouchAnimationConfigModel (defined in JJCollectionViewTouchAnimationConfigModel.h) stores the animation parameters including transformScaleSx, transformScaleSy, startDuration, endDuration, and isCellsAnimationEnable. This model allows you to customize the scale factor and timing for individual sections.
Delegate callbacks in the JJCollectionViewDelegateRoundFlowLayout protocol provide granular control. The isDecorationViewShowAnimationAtIndex: method determines whether a specific section should animate, while animationConfigModelForSection: returns a custom configuration model for that section.
How Touch Animations Work Internally
The animation pipeline executes across three distinct phases within the library's source files.
Layout Preparation Phase
During prepareLayout in JJCollectionViewRoundFlowLayout.m (lines 99-121), the layout creates JJCollectionViewRoundLayoutAttributes for each section's decoration view. If isDecorationViewTouchAnimationEnable is YES, the layout sets attr.isTouchAnimationEnable = YES and attaches a configuration model. When the global flag is NO, the layout checks the delegate method isDecorationViewShowAnimationAtIndex: to determine eligibility per section.
Touch Event Handling
The actual animation logic resides in JJCollectionReusableView.m. When a touch begins, touchesBegan: triggers touchAnimationEventWithScaleSxPoint:scaleSyPoint:duration:isCellsAnimationEnable: using the start values from the configuration model. When the touch ends or cancels (touchesEnded: or touchesCancelled:), the method executes again with end values (typically restoring scale to 1.0).
According to lines 88-115 of the implementation, this method performs a UIView animation on the decoration view itself. When isCellsAnimationEnable is set to YES in the configuration model, the animation concurrently scales every visible cell belonging to the same section.
Selection Callback
After a tap completes, decorationViewUserDidSelectEvent forwards the event to the optional delegate method collectionView:didSelectDecorationViewAtIndexPath: (lines 23-30 in JJCollectionReusableView.m), allowing you to respond to user interaction after the animation finishes.
Global Enablement with Default Animations
For simple implementations where all sections should use identical animation behavior, enable the feature globally on the layout instance.
// In your view controller setup
JJCollectionViewRoundFlowLayout *layout = [[JJCollectionViewRoundFlowLayout alloc] init];
layout.isDecorationViewTouchAnimationEnable = YES;
// The layout uses default JJCollectionViewTouchAnimationConfigModel
// values (scale 0.98, 0.3s duration) automatically
UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds
collectionViewLayout:layout];
This approach requires no delegate implementation. The layout automatically applies a subtle scale-down effect (0.98x) with 0.3-second animation durations to all section backgrounds when touched.
Per-Section Control with Custom Parameters
For advanced use cases requiring different animation styles per section, implement the JJCollectionViewDelegateRoundFlowLayout protocol methods.
First, adopt the protocol in your view controller:
@interface MyViewController () <JJCollectionViewDelegateRoundFlowLayout>
@end
Then implement the delegate methods to conditionally enable animations and return custom configuration models:
- (BOOL)collectionView:(UICollectionView *)cv
layout:(UICollectionViewLayout *)layout
isDecorationViewShowAnimationAtIndex:(NSInteger)section {
// Enable animation only for even sections
return (section % 2 == 0);
}
- (JJCollectionViewTouchAnimationConfigModel *)collectionView:(UICollectionView *)cv
layout:(UICollectionViewLayout *)layout
animationConfigModelForSection:(NSInteger)section {
JJCollectionViewTouchAnimationConfigModel *model = [JJCollectionViewTouchAnimationConfigModel createDefaultModel];
// Create a "bouncy" press effect
model.transformScaleSx = 0.92;
model.transformScaleSy = 0.92;
model.startDuration = 0.15;
model.endDuration = 0.25;
model.isCellsAnimationEnable = YES; // Animate cells along with background
return model;
}
The createDefaultModel class method provides a baseline configuration that you can modify before returning. When isCellsAnimationEnable is YES, the entire section including all visible cells scales together, creating a cohesive pressed state.
Handling Decoration View Selection
To receive callbacks when users tap the decoration view background, implement the selection delegate method:
- (void)collectionView:(UICollectionView *)cv
didSelectDecorationViewAtIndexPath:(NSIndexPath *)indexPath {
NSLog(@"User tapped decoration view in section %ld", (long)indexPath.section);
// Navigate to detail view or update UI state
}
This method fires after the touch animation completes, ensuring the visual feedback finishes before your logic executes.
Creating Reusable Animation Configurations
For applications using consistent animation styles across multiple view controllers, factory methods provide clean code reuse:
@implementation JJCollectionViewTouchAnimationConfigModel (CustomConfigs)
+ (instancetype)heavyPressConfig {
JJCollectionViewTouchAnimationConfigModel *model = [self createDefaultModel];
model.transformScaleSx = 0.90;
model.transformScaleSy = 0.90;
model.startDuration = 0.1;
model.endDuration = 0.2;
model.isCellsAnimationEnable = NO;
return model;
}
@end
Return this custom instance from your delegate's animationConfigModelForSection: method whenever you need the "heavy press" effect.
Summary
- Global activation requires only setting
isDecorationViewTouchAnimationEnable = YESon theJJCollectionViewRoundFlowLayoutinstance. - Per-section customization implements
isDecorationViewShowAnimationAtIndex:andanimationConfigModelForSection:in the delegate protocol. - Animation parameters including scale factors, durations, and cell participation are controlled via
JJCollectionViewTouchAnimationConfigModel. - Touch handling occurs in
JJCollectionReusableView.musingUIViewanimations triggered bytouchesBegan:andtouchesEnded:. - Selection detection uses the
collectionView:didSelectDecorationViewAtIndexPath:delegate callback defined inJJCollectionViewRoundFlowLayout.h.
Frequently Asked Questions
How do I disable touch animations for specific sections while keeping them enabled globally?
Set layout.isDecorationViewTouchAnimationEnable = YES to enable the feature globally, then implement the delegate method isDecorationViewShowAnimationAtIndex: and return NO for sections that should not animate. This method is checked in JJCollectionViewRoundFlowLayout.m (lines 99-121) when the global flag is disabled or when determining per-section eligibility.
Can I animate the cells inside the section when touching the decoration view?
Yes. Set the isCellsAnimationEnable property to YES on your JJCollectionViewTouchAnimationConfigModel before returning it from the delegate. When this flag is enabled, the touchAnimationEventWithScaleSxPoint:… method in JJCollectionReusableView.m (lines 88-115) applies the same scale transform to all visible cells in the section simultaneously with the decoration view.
What are the default animation values if I don't provide a custom configuration model?
If you enable touch animations globally without implementing animationConfigModelForSection:, the layout uses the default model created by [JJCollectionViewTouchAnimationConfigModel createDefaultModel]. This typically applies a subtle scale of 0.98x with 0.3-second animation durations for both the start (press down) and end (release) states.
Why isn't my didSelectDecorationViewAtIndexPath: delegate method being called?
Ensure your view controller conforms to JJCollectionViewDelegateRoundFlowLayout and that you have set the collection view's delegate property. The callback originates from decorationViewUserDidSelectEvent in JJCollectionReusableView.m (lines 23-30), which only executes if the delegate responds to the selector after the touch animation sequence completes.
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 →