移除UICollectionView中UIAttachmentBehavior的振荡



我试图重新创建您在我的UICollectionView的iOS消息应用程序中看到的spring行为。像消息一样,它将根据文本大小具有不同的单元格大小。我已经创建了一个自定义的UICollectionViewFlowLayout,它确实将行为添加到UICollectionView,但是在用户停止滚动后,消息气泡继续轻微振荡。我已经尝试了length, dampingspring值的任何数量的组合,但振荡从未消失。

在阅读了其他堆栈问题之后,我确实发现了这个评论

为了防止振荡,有必要在二次尺度上动态地增加阻尼因子,因为附加视图越来越接近它们的附着点。& lt;

但是我真的不确定从哪里开始实现我目前拥有的东西。任何帮助或指导将不胜感激。

下面是我在UICollectionViewFlowLayout上创建当前效果的代码。

- (void) prepareLayout {
    [super prepareLayout];
    
    CGRect originalRect = (CGRect){.origin = self.collectionView.bounds.origin, .size = self.collectionView.frame.size};
    CGRect visibleRect = CGRectInset(originalRect, -50, -50);
    
    NSArray *itemsInVisibleRectArray = [super layoutAttributesForElementsInRect:visibleRect];
    NSSet *itemsIndexPathsInVisibleRectSet = [NSSet setWithArray:[itemsInVisibleRectArray valueForKey:@"indexPath"]];
    
    
    NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(UIAttachmentBehavior *behaviour, NSDictionary *bindings) {
        BOOL currentlyVisible = [itemsIndexPathsInVisibleRectSet member:[[[behaviour items] firstObject] indexPath]] != nil;
        return !currentlyVisible;
    }];
    NSArray *noLongerVisibleBehaviours = [self.animator.behaviors filteredArrayUsingPredicate:predicate];
    
    [noLongerVisibleBehaviours enumerateObjectsUsingBlock:^(id obj, NSUInteger index, BOOL *stop) {
        [self.animator removeBehavior:obj];
        [self.visibleIndexPathsSet removeObject:[[[obj items] firstObject] indexPath]];
    }];
    
    
    NSPredicate *newPredicate = [NSPredicate predicateWithBlock:^BOOL(UICollectionViewLayoutAttributes *item, NSDictionary *bindings) {
        BOOL currentlyVisible = [self.visibleIndexPathsSet member:item.indexPath] != nil;
        return !currentlyVisible;
    }];
    NSArray *newlyVisibleItems = [itemsInVisibleRectArray filteredArrayUsingPredicate:newPredicate];
    CGPoint touchLocation = [self.collectionView.panGestureRecognizer locationInView:self.collectionView];
    
    
    [newlyVisibleItems enumerateObjectsUsingBlock:^(UICollectionViewLayoutAttributes *item, NSUInteger idx, BOOL *stop) {
        CGPoint center = item.center;
        UIAttachmentBehavior *springBehaviour = [[UIAttachmentBehavior alloc] initWithItem:item attachedToAnchor:center];
        
        springBehaviour.length = 0.1f;
        springBehaviour.damping = 3.0f;
        springBehaviour.frequency = 2.8f;
        
        if (!CGPointEqualToPoint(CGPointZero, touchLocation)) {
            CGFloat yDistanceFromTouch = fabs(touchLocation.y - springBehaviour.anchorPoint.y);
            CGFloat xDistanceFromTouch = fabs(touchLocation.x - springBehaviour.anchorPoint.x);
            CGFloat scrollResistance = (yDistanceFromTouch + xDistanceFromTouch) / 1500.0f;
            
            if (self.latestDelta < 0) {
                center.y += MAX(self.latestDelta, self.latestDelta*scrollResistance);
            }
            else {
                center.y += MIN(self.latestDelta, self.latestDelta*scrollResistance);
            }
            item.center = center;
        }
        
        [self.animator addBehavior:springBehaviour];
        [self.visibleIndexPathsSet addObject:item.indexPath];
    }];
}

你可以用两个步骤来修复。

  1. 行为添加动作当首字母大写时,以确保单元格的中心在动画
  2. 中不会改变
springBehaviour.action = ^{
            CGPoint itemCenter = item.center;
            itemCenter.x = center.x;
            item.center = itemCenter;
        };
  • 删除/重新添加当collectionview停止滚动的行为。要做到这一点,你需要实现一个scrollview委托方法,并在该方法中删除/重新添加行为。
  • - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
    {
        ZZHCollectionFlowLayout *flowLayout = self.collectionView.collectionViewLayout;
        if ([flowLayout isKindOfClass:[ZZHCollectionFlowLayout class]])
        {
            [flowLayout removeAnimationBehavior];
        }
        else
        {
            // Your NSAssertionHandler
        }
    }
    - (void)removeAnimationBehavior
    {
        NSArray *behaviors = self.dynamicAnimator.behaviors;
        [self.dynamicAnimator removeAllBehaviors];
        for (UIDynamicBehavior *obj in behaviors)
        {
            [self.dynamicAnimator addBehavior:obj];
        }
    }
    
    顺便说一句,如果有办法改变阻尼来修复,我想听听!

    相关内容

    • 没有找到相关文章

    最新更新