Отключение вертикального перемещения 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.

Другие вопросы по тегам