📜 ⬆️ ⬇️

Using UIDynamicAnimator from UIKit Dynamics when creating tables based on UICollectionView

As is known in the latest version of the SDK (UIKit Dynamics framework), developers can define dynamic behavior for UIView objects, as well as other objects that accept the UIDynamicItem protocol.

In this article I want to share the experience of using such objects.

The goal was to make an animation similar to the one used in the Messages application on iOS 7:

image
')
After searching and studying the documentation, it was decided to use the UIDynamicAnimator in conjunction with the UICollectionView .

To do this, it was necessary to create a descendant class UICollectionViewFlowLayout :

#import <UIKit/UIKit.h> @interface DVCollectionViewFlowLayout : UICollectionViewFlowLayout @end 


add property with type UIDynamicAnimator

 #import "DVCollectionViewFlowLayout.h" @interface DVCollectionViewFlowLayout() //- @property (nonatomic, strong) UIDynamicAnimator *dynamicAnimator; @end @implementation DVCollectionViewFlowLayout @synthesize dynamicAnimator = _dynamicAnimator; -(id)initr{ self = [super init]; if (self){ _dynamicAnimator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout:self]; } return self; } 


Dynamic behavior becomes active when we add it to an object that is an instance of a UIDynamicAnimator. The animator defines the context in which the dynamic behavior is performed.

After that we have to redefine in it the following functions:

 #import "DVCollectionViewFlowLayout.h" // ......... - (void)prepareLayout{ [super prepareLayout]; CGSize contentSize = [self collectionViewContentSize]; NSArray *items = [super layoutAttributesForElementsInRect:CGRectMake(0, 0, contentSize.width, contentSize.height)]; if (items.count != self.dynamicAnimator.behaviors.count) { [self.dynamicAnimator removeAllBehaviors]; for (UICollectionViewLayoutAttributes *item in items) { UIAttachmentBehavior *springBehavior = [[UIAttachmentBehavior alloc] initWithItem:item attachedToAnchor:item.center]; //       ( ) springBehavior.length = 0.f; springBehavior.damping = 1.f; springBehavior.frequency = 6.8f; [self.dynamicAnimator addBehavior:springBehavior]; } } } - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect{ return [self.dynamicAnimator itemsInRect:rect]; } - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{ return [self.dynamicAnimator layoutAttributesForCellAtIndexPath:indexPath]; } - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{ CGFloat scrollDelta = newBounds.origin.y - self.collectionView.bounds.origin.y; CGPoint touchLocation = [self.collectionView.panGestureRecognizer locationInView:self.collectionView]; for (UIAttachmentBehavior *springBehavior in self.dynamicAnimator.behaviors) { CGPoint anchorPoint = springBehavior.anchorPoint; CGFloat touchDistance = fabsf(touchLocation.y - anchorPoint.y); //       ( ) CGFloat resistanceFactor = 0.002; UICollectionViewLayoutAttributes *attributes = springBehavior.items.firstObject; CGPoint center = attributes.center; float resistedScroll = scrollDelta * touchDistance * resistanceFactor; float simpleScroll = scrollDelta; float actualScroll = MIN(abs(simpleScroll), abs(resistedScroll)); if(simpleScroll < 0){ actualScroll *= -1; } center.y += actualScroll; attributes.center = center; [self.dynamicAnimator updateItemUsingCurrentState:attributes]; } return NO; } -(void)dealloc{ [self.dynamicAnimator removeAllBehaviors]; self.dynamicAnimator = nil; } 


The UIAttachmentBehavior object defines the relationship between the dynamic item element of the UICollectionViewLayoutAttributes class and the item.center point (the center of this element). When one element or point moves, the attached element also moves. Using the damping and frequency properties, we can specify how the behavior changes over time.

Source

Useful links about animation in iOS 7:


Source: https://habr.com/ru/post/198890/


All Articles