В данной статье я хочу поделиться опытом использования таких объектов.
Целью было сделать анимацию, аналогичную той, что используется в приложении Messages на iOS 7:
После поисков и изучения документации решено было использовать UIDynamicAnimator в связке с UICollectionView.
Для этого необходимо было создать класс-наследник UICollectionViewFlowLayout:
#import <UIKit/UIKit.h> @interface DVCollectionViewFlowLayout : UICollectionViewFlowLayout @end
добавить свойство с типом 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; }
Динамическое поведение становится активным, когда мы его добавляем к объекту, который является экземпляром UIDynamicAnimator. Аниматор определяет контекст, в котором динамическое поведение выполняется.
После этого мы должны переопределить в нём нижеперечисленные функции:
#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; }
Объект UIAttachmentBehavior определяет связь между динамическим элементом item класса UICollectionViewLayoutAttributes и точкой item.center (центром этого элемента). Когда один элемент или точка перемещается, присоединенный элемент также перемещается. C помощью свойств damping и frequency мы можем указать как изменится поведение с течением времени.
Полезные ссылки про анимации в iOS 7:
- Introduction to UIKit Dynamics
- UIKit Dynamics Tutorial
- iOS 7 SDK: Обзор изменений
- Эффект параллакса в iOS приложениях
- Осваиваем Core Motion в iOS
ссылка на оригинал статьи http://habrahabr.ru/post/198890/
Добавить комментарий