Отключение вертикального перемещения UIAttachmnetBehavior в UICollectionView
Я пытаюсь имитировать сообщения приложение весенней анимации в горизонтальном UICollectionView
Я использовал UIAttachmentBehavior в моем подклассе UICollectionViewFlowLayout. но проблема в том, что когда я прокручиваю по горизонтали, клетки также перемещаются по вертикали и по горизонтали как-то вращательным движением!
Я следовал этому уроку:
реализация упругого uicollectionviewlayout с помощью uikitdynamics
и используется в моем collectionView. Я также следил за сессией WWDC 2013 217- Изучение представлений прокрутки на iOS 7. Но проблема все еще остается!
У кого-нибудь есть идеи, как мне решить эту проблему?
-(id)initWithCoder:(NSCoder *)aDecoder{
self = [super initWithCoder:aDecoder];
if (self){
_dynamicAnimator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout:self];
}
return self;
}
- (void)prepareLayout{
[super prepareLayout];
CGSize contentSize = [self collectionViewContentSize];
NSArray *items = [super layoutAttributesForElementsInRect:CGRectMake(0, 0, contentSize.width, 500)];
if (items.count != _dynamicAnimator.behaviors.count) {
[_dynamicAnimator removeAllBehaviors];
for (UICollectionViewLayoutAttributes *item in items) {
UIAttachmentBehavior *springBehavior = [[UIAttachmentBehavior alloc] initWithItem:item attachedToAnchor:item.center];
springBehavior.length = 0.f;
springBehavior.damping = 0.5f;
springBehavior.frequency = 0.8f;
[_dynamicAnimator addBehavior:springBehavior];
}
}
}
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect{
return [_dynamicAnimator itemsInRect:rect];
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{
return [_dynamicAnimator layoutAttributesForCellAtIndexPath:indexPath];
}
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{
CGFloat scrollDelta = newBounds.origin.x - self.collectionView.bounds.origin.x;
CGPoint touchLocation = [self.collectionView.panGestureRecognizer locationInView:self.collectionView];
for (UIAttachmentBehavior *springBehavior in _dynamicAnimator.behaviors) {
CGPoint anchorPoint = springBehavior.anchorPoint;
CGFloat touchDistance = fabsf(touchLocation.x - anchorPoint.x);
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.x += actualScroll;
attributes.center = center;
[_dynamicAnimator updateItemUsingCurrentState:attributes];
}
return NO;
}
3 ответа
У меня была та же проблема в моем приложении. Проблема в этой строке: UIAttachmentBehavior *springBehavior = [[UIAttachmentBehavior alloc] initWithItem:item attachedToAnchor:item.center];
Проблема в том, что центр элемента возвращает числа с плавающей запятой с десятичными знаками. Затем iOS округляет их до числа с плавающей точкой с 0 десятичными знаками, из-за чего точка привязки не центрируется должным образом, поэтому элемент отскакивает.
Решение состоит в том, чтобы убедиться, что рамка вашего элемента делится на два по высоте и ширине, прежде чем закрепить его. Затем убедитесь, что item.center возвращает значения X и Y, которые являются плавающими без десятичных знаков, и анимация будет работать нормально.
ПРИМЕЧАНИЕ. Несмотря на то, что iOS7 работает отлично, я вижу проблемы в iOS8, подобные этой, и это решение не работает.
Ну у меня была эта проблема - iOS8.
Теперь это прошло благодаря этому посту.
Я добавлял дополнительные представления в UICollectionView, в котором уже работала UIDynamics. Затем я добавил несколько дополнительных видов, которые были созданы на основе обычных ячеек. Вычисление вернет значение float для высоты (не 0 десятичных дробей). И я полагаю, как сказал Пол, iOS затем должна выполнить некоторое округление, которое теперь создает y-дельту, которую я не хотел. Это то, что вызывает колебательное движение.
Округляя мою дополнительную высоту вида, проблема исчезла. Я получаю постоянные центры 7,5, поэтому мой рост не делится на 2, но он все еще работает.
Вот как теперь вычисляются мои дополнительные виды
UICollectionViewLayoutAttributes *attributes = [self.dynamicAnimator layoutAttributesForCellAtIndexPath:indexPath];
// put supp view at beginning of cell
// round off height or wierd oscillations will begin as iOS must round also
CGRect suppViewFrame = CGRectMake(attributes.frame.origin.x - 44.0 / 2,
attributes.frame.origin.y - 44.0,
44.0,
roundf(44.0 + attributes.frame.size.height / 2));
Все, что я добавил, было округлением до части высоты вычисления CGRect.
И вуаля - это работает.
Надеюсь, это поможет кому-то - счастливое кодирование
Я вижу точно такую же проблему в iOS 8 - кажется, что, хотя UICollisionBehavior разрешает создание границ, то же самое не существует для UIAttachmentBehavior (хотя документация класса упоминает об этом для UIAttachmentBehavior). Я думаю, что краткосрочным решением может быть просто перейти к UIDynamicItemBehavior, который выглядит более гибким. Однако интересно узнать, что изменилось с iOS 7 на iOS 8.